将Type变量限制为特定的类或子类



我在C#中工作,希望在我的类中存储一个类型,但我希望该类型属于某个类或它的子类。

这可能是代码的样子:

public class Factory
{
public Type typeToInstantiate where Type: ABaseType;
public Factory(Type instantiateThis where Type : ABaseType)
{
this.typeToInstantiate = instantiateThis;
}
public void DoTheThing()
{
var newObj = (ABaseType)Activator.CreateInstance(typeToInstantiate);
newObj.PrintSomethingToConsole();
}
}

public abstract class ABaseType
{
public abstract void PrintSomethingToConsole();
}
public abstract class ASubType : ABaseType
{
public override void PrintSomethingToConsole()
{
System.Console.WriteLine("Something");
}
}
public abstract class AnotherSubType : ABaseType
{
public override void PrintSomethingToConsole()
{
System.Console.WriteLine("Something else");
}
}
public static void Main(string[] args)
{
List<Factory> factories = new List<Factory>();
factories.Add(new Factory(typeof(AnotherSubType)));
factories.Add(new Factory(typeof(ASubType)));
foreach (var factory in factories) factory.PrintSomethingToConsole();
}

我试图解决的问题(以防有人有更好的想法(:我正在创建一种工厂,它将实例化一些指定类型的对象。因此,当创建这个工厂时,它将使用它应该实例化的类型来创建。然而,这个工厂有一个特定的目的,所以它应该只实例化特定类(或该类的子类(的对象。

你在问这样的问题吗:

class C<T> where T: SomeBaseClass
{
}

如果需要在运行时检查,可以在逻辑中使用TypeIsAssignableFrom。例如

public class MyFactory
{
Type baseType = typeof(MyBaseType);
IDictionary<string, Type> typeMap = new Dictionary<string, Type>() {}
public void RegisterType(string typeName, Type type) 
{
if (!(type == baseType || baseType.IsAssignableFrom(type)) throw new ArgumentException(nameof(type));
typeMap.Add(typeName, type);    
}
}

有关更详细的示例,请参阅此处的代码:https://stackoverflow.com/a/53121973/361842

给定以下类:

public abstract class ABaseType
{
public abstract void PrintSomethingToConsole();
}
public class ASubType : ABaseType
{
public override void PrintSomethingToConsole()
{
System.Console.WriteLine("Something");
}
}
public class AnotherSubType : ABaseType
{
public override void PrintSomethingToConsole()
{
System.Console.WriteLine("Something else");
}
}

(快速提示:如果要创建类AnotherSubType和ASubType的实例,则它们不能是抽象的(。

你的工厂可以这样重构:

public class Factory 
{
private readonly List<ABaseType> _instances;
public Factory()
{
_instances = new List<ABaseType>();
}
public void Register<T>()  where T : ABaseType, new()
{
// creates a new instance of the object
// As an alternative, save the type and create a new instance in DoTheThing()
var instance = new T();
_instances.Add(instance);
}
public void DoTheThing()
{
_instances.ForEach(x => x.PrintSomethingToConsole());
}
}

使用代码:

var factory = new Factory();
factory.Register<AnotherSubType>();
factory.Register<ASubType>();
factory.DoTheThing();

输出:

其他

我理解您的要求如下:

  1. 您想要一个可以包含其他类型的类,仅限于BaseType的子类,这是类型安全的
  2. 此类的不同实例必须能够存储在同一类型的变量中

您可以使用协方差和类型约束来执行此操作。

声明协变接口:

public interface IMyFactory<out T>
{
T Resolve();
}

在课堂上实现它:

public class MyFactory<T> : IMyFactory<T> where T :BaseType, new()
{
public readonly Type typeToInstantiate;
public MyFactory()
{
typeToInstantiate = typeof(T);
}
public T Resolve()
{
return new T();
}
}

并称之为:

public class Program
{
public static void Main()
{
IMyFactory<BaseType> factory;
{
factory = new MyFactory<BaseType>();
var instance = factory.Resolve();
Console.WriteLine(instance.GetType().FullName);
}
{
factory = new MyFactory<DerivedType>() as IMyFactory<BaseType>;
var instance = factory.Resolve();
Console.WriteLine(instance.GetType().FullName);
}
}
}

请注意,这里只声明了一个变量,但它可以包含任何一种类型的工厂,每个工厂都将在运行时解析为正确的类型,如输出中所示。

输出:

Example.BaseType
Example.DerivedType

这里有一个DotNetFiddle的链接。

最新更新