如何将<t>转换为泛型方法的基类型?</t>

时间:2010-08-30 03:32:58

标签: c# entity-framework type-conversion

我有一个通用的CRUD类来执行添加,删除,选择,创建我的实体对象。

其中一个 - 消息有两个派生类 - order_message和report_message。

我的问题是,在我的泛型类中,我需要一个objectset来执行crud操作,但是objectset不接受派生类类型,它只接受基类类型。

这是我收到的错误:

  

没有为指定的实体类型'CustomerWebPortal_Entities.Order_Message'定义EntitySet。如果'CustomerWebPortal_Entities.Order_Message'是派生类型,请改用基类型。

我尝试使用typeof(T).BaseType来替换T,并且原因不起作用。

我该如何纠正?

这是泛型类的概述:

 public abstract class baseCrudDao<T> : ICrudDao<T> where T : class
{
    private System.Data.Objects.ObjectContext _context;

    private System.Data.Objects.ObjectSet<T> _entity; 
    public baseCrudDao()
    {

        _context = new CustomerWebPortalEntities();
        _entity = _context.CreateObjectSet<T>(); <-- error at here, only accept base type

    }

2 个答案:

答案 0 :(得分:3)

好吧,我终于有机会按照建议编写原型。我认为像这样的东西会起作用,但我还没有测试过。现在可以针对IObjectSet<>成员定义所有crud方法。

public class Crud<EntityType> where EntityType : class
{
    private readonly ObjectContext Context;
    private readonly IObjectSet<EntityType> Entities;

    public Crud(ObjectContext context)
    {
        Context = context;

        Type BaseType = GetBaseEntityType();

        if (BaseType == typeof(EntityType))
        {
            Entities = Context.CreateObjectSet<EntityType>();
        }
        else
        {
            Entities = (IObjectSet<EntityType>)Activator.CreateInstance(typeof(ObjectSetProxy<,>).MakeGenericType(typeof(EntityType), BaseType), Context);
        }
    }

    private static Type GetBaseEntityType()
    {
        //naive implementation that assumes the first class in the hierarchy derived from object is the "base" type used by EF
        Type t = typeof(EntityType);

        while (t.BaseType != typeof(Object))
        {
            t = t.BaseType;
        }

        return t;
    }
}

internal class ObjectSetProxy<EntityType, BaseEntityType> : IObjectSet<EntityType>
    where EntityType : BaseEntityType
    where BaseEntityType : class
{
    private readonly IObjectSet<BaseEntityType> Entities;

    public ObjectSetProxy(ObjectContext context)
    {
        Entities = context.CreateObjectSet<BaseEntityType>();
    }

    public void AddObject(EntityType entity)
    {
        Entities.AddObject(entity);
    }

    //TODO: implement remaining proxy methods

    public IEnumerator<EntityType> GetEnumerator()
    {
        return Entities.OfType<EntityType>().GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public Type ElementType
    {
        get { return typeof(EntityType); }
    }

    public Expression Expression
    {
        get { return Entities.OfType<EntityType>().Expression; }
    }

    public IQueryProvider Provider
    {
        get { return Entities.Provider; }
    }
}

答案 1 :(得分:0)

一种解决方法是使用两个泛型类型参数(在基类上),例如

public abstract class baseCrudDao<T, U> : ICrudDao<T> where U : class, T: U
{
    ...
    public baseCrudDao()
    {
        _context = new CustomerWebPortalEntities();
        _entity = _context.CreateObjectSet<U>(); <-- error at here, only accept base type
    }
    ...
}

使用Message代替U.如果你有很多类型而不是所有类型都有继承关系,那么约束T:U将不起作用,你需要使用T:class约束。我还建议你创建另一个骨架基类,用于其他类型,如

public abstract class base2CrudDao<T> : baseCrudDao<T, T>

这样您就不必为没有继承关系的类指定U参数。