【问题标题】:Generics & Reflection - GenericArguments[0] violates the constraint of type泛型和反射 - GenericArguments[0] 违反了类型的约束
【发布时间】:2011-09-14 10:30:47
【问题描述】:

我一直在努力解决这个问题,基本上我正在尝试实现一个通用的存储库工厂,它的调用如下:

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]', on '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();
    }

【问题讨论】:

  • 您那里缺少退货声明吗?您是否粘贴了该方法的完整副本?
  • 另外,当您明确打算调用带参数的构造函数时,为什么还要检查是否存在无参数构造函数?如果你有一个无参数的构造函数,它很可能是 GetConstructors 返回的第 0 个构造函数,在这种情况下,使用参数调用它会失败。
  • 是的,抱歉,'return default(T)' 应该放在最后。
  • 关于无参数构造函数的检查?你说的是对的,我只是想看看我是不是做错了什么。

标签: c# .net generics reflection factory-pattern


【解决方案1】:

您的代码尝试创建DocumentLibraryRepository&lt;IRepository&lt;Document&gt;&gt; 的实例而不是DocumentLibraryRepository&lt;Document&gt;

您想改用此代码:

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

【讨论】:

  • 对不起,我应该补充一点: public interface IRepository where T : class { void Add(T entity);无效删除(T实体);无效更新(T实体); T FindById(int entityId); IEnumerable Find(string camlQuery); IEnumerable All(); }
  • @Bevan:好的。请参阅我更新的答案。这应该可以解决您的问题。
【解决方案2】:

这表明您可能在泛型类型DocumentLibraryRepository&lt;T&gt; 上使用了where 约束,而PerpetualDocument 类型与该约束不匹配

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      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]' 违反 类型参数 'TEventArgs' .. 在方法 Run() 上的约束。

      我不知道这是否是 .NET 错误,但在我的情况下,我解决了这个问题,将 A 类中的 TypedEvent 属性类型从类型为 EventHandler&lt;B&gt; 更改为 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";
          }
      }
      

      希望对大家有所帮助。

      【讨论】:

        【解决方案5】:

        我在 Resharper 的建议下将泛型类型更改为抽象时遇到了这个问题,显然它无法实例化并导致此错误。

        删除了抽象,method.MakeGenericMethod(type) 行再次起作用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-13
          • 2012-12-29
          • 1970-01-01
          相关资源
          最近更新 更多