是否有任何方法可以关联两个类型,以允许泛型方法根据输入参数的类型返回相关类型



我正在编写一个通用的扩展器扩展方法,该方法将对数据库对象的集合进行操作,并将它们和所有选定的子模型转换为内部模型对象。我知道EF可以帮助实现这一点,但目前我正在使用的其他代码库中并没有使用它,这不是问题所在。

问题是:有没有任何方法可以将类耦合,这样泛型就会知道是否使用了一个类,另一个类是隐含的?

为了解释。。。

我想有一个方法

public static IEnumerable<TResult> ExpandAsModels<TSource,TResult>(this IQueryable<TSource> source)

它将成功处理类型绑定,所以我不必每次都填写模板值。即代替

var result = datasource.ExpandAsModel<DBCarObject,CarModel>();

我想能够使用

var result = datasource.ExpandAsModel();

我知道这听起来很迂腐,但我正在努力生成初级程序员不会塞满的代码。我想要的是能够将SourceTypes和ResultTypes关联起来。例如,在DBCarObject和CarModel之间具有显式关联。

我尝试通过使DBCarObject实现interface IDBObject<CarModel>并将扩展方法定义为来实现这一点

public static IEnumerable<TResult> ExpandAsModels<TSource,TResult>(this IQueryable<TSource> source)
where TSource: IDBObject<TResult>

这可以防止不匹配的对象,但不能自动处理泛型(因此不能使用简单的var result = datasource.ExpandAsModel();调用形式(

有人能解释一下是否有办法做到这一点吗?似乎有很多情况下,类型以相关的方式操作,可以利用这种关联。

如果我在设计C#,我想我会追求一个可能被使用的功能,比如。。。

class a {}
class b {}
class x {
associated a mymodel;
}
class y {
associated b mymodel;
}
TResult doSomething<TResult,TSource>(TSource data) 
where TSource has association mymodel
where TResult : mymodel   

这将要求TSource是一个具有名为mymodel的关联的对象并且TResult将是由关联定义的mymodel的类型。

最终结果是doSomething(new x());将具有a的返回类型,而doSomething(new y());将具有b的返回类型。

要么这样,要么让编译器能够像我上面的例子一样通过泛型进行跟踪。

如果从扩展方法中删除TSource,编译器可以推导类型参数;

public interface IDBObject<TResult>
{
}
public static IEnumerable<TResult> ExpandAsModels<TResult>(this IQueryable<IDBObject<TResult>> source)
{
// TODO
}
public class ClientView { 
}
public class Client : IDBObject<ClientView>
{
}
public static void Test() {
IQueryable<Client> query = null;
var result = query.ExpandAsModels();
}

如果您需要您的扩展方法来方便地访问类型TSource,您可以使您的泛型接口递归;

public interface IDBObject<TSource, TResult> where TSource : IDBObject<TSource, TResult>
{
}
public static IEnumerable<TResult> ExpandAsModels<TSource, TResult>(this IQueryable<IDBObject<TSource, TResult>> source) where TSource : IDBObject<TSource, TResult>
{
// TODO
}
public class Client : IDBObject<Client, ClientView>
{
}

也许是这样的:

public abstract class SourceBase<TResult> where TResult : TargetBase
{
public abstract TResult MapToResult();
}
public class TargetBase
{
}

public class SourceA : SourceBase<TargetA>
{
public string SourceProperty { get; set; }
public override TargetA MapToResult()
{
// here maps the data to target;
var data = new TargetA();
data.TargetProperty = this.SourceProperty;
return data;
}
}
public class TargetA : TargetBase
{
public string TargetProperty { get; set; }
}

分机:

public static TargetBase ExpandAsModels<TSource>(this IQueryable<TSource> source) where TSource : SourceA, new()
{
TSource data = new TSource();
// fill the data reading from db 
// Maps and return the value
return data.MapToResult();
}

使用时:

IQueryable<SourceA> MySourceData = ...
MySourceData.ExpandAsModels();

最新更新