c# - 在 C# 中,我可以根据使用的类型 (T) 使用泛型的特定实现吗

标签 c# generics inheritance

我正在尝试在 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/

相关文章:

c# - 使用 C# XmlDocument 选择相对 XPath 节点

c# - Visual Studio C# 调试器 - 当前不会命中断点

Java 泛型 : Restricting a class to specific implementations.

c++ - 在 C++ 中访问父命名空间

python - 如何在Python中通过继承正确启动子类?

c++ - 如何创建采用基类和派生类的函数的专用版本和默认版本?

c# - 如何将 json 添加到 RestSharp POST 请求

c# - 使用 C# 打印控件的整个区域

java - map 与泛型的递归合并

java - Map 中 Set 的通配符 - 返回类型不兼容 - 为什么?