我正在尝试在 WPF/MVVM/Entity Framework 中创建一个尽可能通用的类结构。我正在使用 Prism & Unity。事实上,我认为这些都不重要,除非我能以某种方式在解决方案中使用 Prism/Unity。
在我需要运行特定于 Type(T) 的代码之前,我有一个已设置且运行良好的系统。
如果类型 T 有匹配的派生类,我真正想要的是以某种方式让系统使用类的非泛型版本,否则我希望它使用泛型版本。
在一个 super 淡化的例子中,我有一个基类:
public class BaseClass<T>
{
public T MyObject;
protected virtual int GetErrorCount()
{
int errorCount = 0;
if (MyObject == null)
errorCount++;
return errorCount;
}
}
还有一个子类:
public class StringClass : BaseClass<String>
{
protected override int GetErrorCount()
{
int errorCount = base.GetErrorCount();
if (MyObject != null && MyObject.Length < 5)
errorCount++;
return errorCount;
}
}
还有一个实现类:
public class ImplementationClass<T>
{
public BaseClass<T> MyBaseObject;
public ImplementationClass()
{
// If T is a string I want to use StringClass instead of the base
// And it should happen automagically
MyBaseObject = new BaseClass<T>();
}
}
我有一些解决此问题的想法,涉及复杂的开关或在 POCO 类上抛出逻辑(逻辑的数据),但这不是我想要做的。
我已经考虑过使用字典和一些查找类的想法,每当我需要解析实际类型时都会使用它们 - 但实际上是 Prism 所做的,所以我认为我可以以某种方式使用它......只是可以弄清楚。
关于如何尽可能通用地完成此任务的任何想法?
弄清楚了,对此有任何反馈吗?我需要注意什么?
解决方案(也允许更改 MyBaseObject):
public static class HelperExt
{
internal static IEnumerable<Type> GetInhiritingTypes(this Type fatherT)
{
return fatherT.Assembly.GetTypes().Where(t => t.IsSubclassOf(fatherT) && !t.IsAbstract);
}
}
public class ImplementationClass<T>
{
private BaseClass<T> _myBaseObject;
public BaseClass<T> MyBaseObject
{
get { return _myBaseObject; }
set
{
Type instType = typeof(BaseDataViewModel<T>).GetInhiritingTypes().FirstOrDefault(t => t.BaseType.GetGenericArguments().Contains(typeof(T)));
if (instType != null)
SetProperty(ref _myBaseObject, (BaseClass<T>)Activator.CreateInstance(instType));
else
SetProperty(ref _myBaseObject, value);
}
}
public ImplementationClass()
{
// If T is a string I want to use StringClass instead of the base
// And it should happen automagically
MyBaseObject = new BaseClass<T>();
}
}
最佳答案
你可以通过一些反射(reflection)来做到这一点,首先是这个辅助函数:
public static IEnumerable<Type> GetInhiritingTypes(this Type fatherT)
{
return fatherT.Assembly.GetTypes().Where(t => t.IsSubclassOf(fatherT) && !t.IsAbstract);
}
然后:
Type genericType = typeof(string);
Type typeToInstantiate = typeof(BaseClass<String>).GetInheritingTypes().FirstOrDefault(t=>t.GetGenericsArguments().Contains(genericType));
if (typeToInstantiate != null)
MyBaseObject = (BaseClass<T>)Activator.CreateInstance(typeToInstantiate);
else
MyBaseObject = new BaseClass<T>();
但是使用这样的方法几乎没有“安全性”。您也可以编写一个工厂函数,它接受一个类名并实例化该类的一个实例。
关于c# - 在 C# 中,我可以根据使用的类型 (T) 使用泛型的特定实现吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36140732/