简体   繁体   English

抽象类型和交互作用的问题作为泛型类型params与new()约束

[英]Problems with abstract types and interafaces as generic type params with the new() constraint

I need to have the generic type parameter as an interface, however I would like to instantiate the type in the generic class (SomeGenericType) as follows: 我需要将泛型类型参数作为接口,但是我想在泛型类(SomeGenericType)中实例化类型,如下所示:

class Program
{
    static void Main(string[] args)
    {
        var val = new SomeGenericType<ISomeInterface>();

        Console.ReadKey();
    }
}

internal class SomeGenericType<T> where T : new()
{
    public SomeGenericType()
    {
        var test = new T();  
    }
}

public class SomeClass : ISomeInterface
{
    public string TestVal { get; set; }
}

public interface ISomeInterface
{
    string TestVal { get; set; }
}

This throws the following compile time error: 这会抛出以下编译时错误:

"ISomeInterface must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method SomeGenericType" “ISomeInterface必须是具有公共无参数构造函数的非抽象类型,以便在泛型类型或方法SomeGenericType中将其用作参数'T'”

I understand why it happens, however I was wondering if there is any way around this problem? 我理解为什么会这样,但是我想知道这个问题是否有任何解决办法?

Thanks. 谢谢。

No, the new() constraint requires that an instance of the type can be created with the syntax 不, new()约束要求可以使用语法创建该类型的实例

new T()

This clearly isn't true of either an abstract class or an interface, only a concrete class with a public parameterless constructor. 这显然不适用于抽象类或接口,只是具有公共无参数构造函数的具体类。

You could defer the problem until runtime by removing the constraint, and using: 您可以通过删除约束将问题推迟到运行时,并使用:

Activator.CreateInstance<T>()

instead to create the object. 而是创建对象。 Then as long as the actual type used at runtime satisfies these constraints, your code will work as you want it to. 然后,只要运行时使用的实际类型满足这些约束,您的代码就会按照您的意愿运行。 However, if you do attempt to use an interface or an abstract class, then you will encounter a runtime error. 但是,如果您尝试使用接口或抽象类,则会遇到运行时错误。

In your specific case, this line would throw an exception 在您的特定情况下,此行将引发异常

var val = Activator.CreateInstance<SomeGenericType<ISomeInterface>>();

You're past the compile-time error, but to no effect. 您已经过了编译时错误,但没有效果。

An alternative idea, which may be irrelevant, but it looks like you are looking for a way to ask for an ISomeInterface , and have an instance of its "default" implementation SomeClass provided. 一个替代的想法,可能是无关紧要的,但看起来你正在寻找一种方法来要求一个ISomeInterface ,并有一个其默认的实现SomeClass提供的实例。 This is the sort of thing that an Inversion of Control (IOC) container can handle for you. 这是控制反转(IOC)容器可以为您处理的事情。 If you want to investigate further, you could look at Spring.NET, Microsoft Unity, AutoFac, LinFu or one of many other frameworks. 如果您想进一步调查,可以查看Spring.NET,Microsoft Unity,AutoFac,LinFu或许多其他框架之一。

The issue here is the new constraint is tied to having a concrete type implementation. 这里的问题是new约束与具体类型实现有关。 This can't ever work with simply and interface or abstract class since they cannot be directly instantiated. 这不能用于简单的接口或抽象类,因为它们不能直接实例化。 You must provide a concrete class here 你必须在这里提供一个具体的课程

var val = new SomeGenericType<SomeClass>()

The problem is, there is no way for the compiler to know which class to instantiate for the given interface. 问题是,编译器无法知道为给定接口实例化哪个类。 As David M points out: 正如大卫M指出:

This is the sort of thing that an Inversion of Control (IOC) container can handle for you 这是控制反转(IOC)容器可以为您处理的事情

I think using a framework might be over kill for this simple requirement. 我认为使用框架可能会因为这个简单的要求而过度杀戮。 What you can do is create a Factory class of your own like this: 你可以做的就是像这样创建一个自己的Factory类:

public class Factory
{
  Dictionary<Type, Type> typeMapping = new Dictionary<Type, Type>();

  public void Register<IType, CType>()
  {
    typeMapping.Add(typeof(IType),typeof(CType));
  }

  public IType Create<IType>()
  {
    Activator.CreateInstance(typeMapping[typeof(IType)]);
  }
}

throw in a few sanity checks and this class should be ready to use. 投入一些健全性检查,这个课程应该可以使用了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM