C#派生泛型类型参数

时间:2013-11-11 12:11:18

标签: c# reflection generic-constraints

我正在使用ASP.NET MVC 4,Entity Framework和C#创建一个Web应用程序,我正在编写抽象超类来封装实体模型和视图模型。细节并不重要,我的问题是我希望这些抽象类实现从任何给定视图模型映射到相应实体模型的函数,反之亦然。

我已经实际使用泛型和反射实现了这样的方法,但是我想让它更整洁。我通过定义EntityModel类来完成所有工作:

public abstract class EntityModel
{
    public TVM MapToViewModel<TVM, TEM>()
        where TVM : ViewModel<TEM>, new()
        where TEM : EntityModel, new()
    { (...) }
}

实际上似乎没有必要将实体模型的类型作为参数发送,因为调用对象将知道它自己的类型并让调用代码指定它为愚蠢的错误打开但我无法弄清楚如何摆脱它。将方法定义为

public TVM MapToViewModel<TVM>()
    where TVM : ViewModel<EntityModel>, new()

似乎很简单,但由于EntityModel是抽象的,因此它会产生编译时错误。有没有办法告诉编译器它必须是EntityModel的衍生物而不是EntityModel本身?或者还有其他更好的解决方案吗?

ViewModel&lt;&gt; class非常相似,定义为:

public abstract class ViewModel<T>
    where T : EntityModel, new()

它正在按预期工作。

2 个答案:

答案 0 :(得分:3)

考虑将映射功能移到实体之外并查看模型类。这将导致更合适的问题分离,以及消除您当前的通用签名问题。 e.g:

public abstract class EntityModel
{
}

public abstract class ViewModel<T>
    where T : EntityModel
{
}

public class ModelMapper<TEM, TVM>
    where TEM : EntityModel, new()
    where TVM : ViewModel<TEM>, new()
{
    public virtual TVM MapToViewModel(TEM entityModel)
    {
        // Default implementation using reflection.
    }

    public virtual TEM MapToEntityModel(TVM viewModel)
    {
        // Default implementation using reflection.
    }
}

答案 1 :(得分:1)

妮可打败了我......只是觉得你可以有一个FromEntity,即:

public abstract class ViewModel<T>
    where T : EntityModel, new()
{
    public static ViewModel<T> FromEntity(T entity)
    {
        throw new NotImplementedException();
    }
}

public abstract class EntityModel
{
    //... properties, methods etc...
}

甚至让ViewModel在构造函数中获取EntityModel

修改

根据您的评论 - 是的,您是对的,我已将参数更改为T而不是EntityModel。

这样做的好处是依赖性来自ViewModel&gt; EntityModel应该是真正的方式:)