泛型和反射 - GenericArguments [0]违反了类型的约束

问题描述 投票:9回答:4

我已经把头发拉了一段时间了,基本上我正在尝试实现一个通用的存储库工厂,调用如下:

var resposFactory = new RepositoryFactory<IRepository<Document>>();

存储库工厂如下所示:

public class RepositoryFactory<T> : IRepositoryFactory<T>
{
    public T GetRepository(Guid listGuid,
        IEnumerable<FieldToEntityPropertyMapper> fieldMappings)
    {
        Assembly callingAssembly = Assembly.GetExecutingAssembly();

        Type[] typesInThisAssembly = callingAssembly.GetTypes();

        Type genericBase = typeof (T).GetGenericTypeDefinition();

        Type tempType = (
            from type in typesInThisAssembly
            from intface in type.GetInterfaces()
            where intface.IsGenericType
            where intface.GetGenericTypeDefinition() == genericBase 
            where type.GetConstructor(Type.EmptyTypes) != null
            select type)
            .FirstOrDefault();

        if (tempType != null)
        {
            Type newType = tempType.MakeGenericType(typeof(T));

            ConstructorInfo[] c = newType.GetConstructors();

            return (T)c[0].Invoke(new object[] { listGuid, fieldMappings });
        }
    }
}

当我尝试调用GetRespository函数时,以下行失败

Type newType = tempType.MakeGenericType(typeof(T));

我得到的错误是:

ArgumentException - GenericArguments [0],'Framework.Repositories.IRepository`1 [Apps.Documents.Entities.PerpetualDocument]','Framework.Repositories.DocumentLibraryRepository`1 [T]'违反了类型'T'的约束。

关于这里出了什么问题的任何想法?

编辑:

存储库的实现如下:

public class DocumentLibraryRepository<T> : IRepository<T>
                                                where T : class, new()
{
   public DocumentLibraryRepository(Guid listGuid, IEnumerable<IFieldToEntityPropertyMapper> fieldMappings)
   {
        ...
   }

   ...
}

而IRepository看起来像:

public interface IRepository<T> where T : class
    {
        void Add(T entity);
        void Remove(T entity);
        void Update(T entity);
        T FindById(int entityId);
        IEnumerable<T> Find(string camlQuery);
        IEnumerable<T> All();
    }
c# .net generics reflection factory-pattern
4个回答
8
投票

您的代码尝试创建DocumentLibraryRepository<IRepository<Document>>而不是DocumentLibraryRepository<Document>的实例。

您想要使用此代码:

var genericArgument = typeof(T).GetGenericArguments().FirstOrDefault();
if (tempType != null && genericArgument != null)
{
    Type newType = tempType.MakeGenericType(genericArgument);

1
投票

这可能表明你可能在泛型类型where上使用了DocumentLibraryRepository<T>约束,并且类型PerpetualDocument与该约束不匹配


1
投票

我有完全相同的错误,但问题和解决方案是不同的。我有4个Model类,1个基类,其中只有3个继承自base,第4个没有。一旦最后一个类继承了基类,错误就消失了。


0
投票

也许我的回答可以帮助那些有同样错误的人。我的情况是:

public class B
{
    public string Name;
}

public class A
{
    public EventHandler<B> TypedEvent;

    public void MyMethod(B item)
    {
        if (TypedEvent != null)
        {
            TypedEvent(null, item);
        }
    }
}

public class T
{
    public void Run()
    {
        A item = new A();
        item.TypedEvent += new EventHandler<B>(ItemEvent);
    }

    private void ItemEvent(object sender, B b)
    {
        b.Name = "Loaded";
    }
}

因此在运行时加载(未执行)Run()方法时,我得到一个异常:

GenericArguments [0] .... System.EventHandler`1 [TEventArgs]'在方法Run()上违反类型参数'TEventArgs'的约束。

我不知道它是否是一个.NET错误,但在我的情况下我解决了这个问题,将TypedEvent类中的A属性类型从类型化的EventHandler<B>更改为EventHandler。我的场景变成:

public class B
{
    public string Name;
}

public class A
{
    public EventHandler TypedEvent;

    public void MyMethod(B item)
    {
        if (TypedEvent != null)
        {
            TypedEvent(item, null);
        }
    }
}

public class T
{
    public void Run()
    {
        A item = new A();
        item.TypedEvent += new EventHandler(ItemEvent);
    }

    private void ItemEvent(object sender, EventArgs e)
    {
        B b = sender as B;
        b.Name = "Loaded";
    }
}

我希望能帮助别人。

© www.soinside.com 2019 - 2024. All rights reserved.