如何实现虚拟静态属性? [英] How to implement virtual static properties?

查看:68
本文介绍了如何实现虚拟静态属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知 C#不支持虚拟静态属性。如何在 C#中实现这种行为?

As far as I know C# doesn't support virtual static properties. How to implement such a behavior in C#?

我想存档一个基类的所有派生类都必须覆盖静态属性。获取派生类型时,我想访问名为 Identifier

I want to archive that all derived classes of a base class must override a static property. Getting a derived type, I want to access to a static property called Identifier

Type t = typeof(DerivedClass);
var identifier= (String) t.GetProperty("Identifier", BindingFlags.Static).GetValue(null, null);


推荐答案

对于那些想到同一件事并达到目标的人通过谷歌搜索发布,请考虑抽象工厂模式,而不是此处的解决方案。

For people who think about the same thing and reach this post by googling, consider abstract factory pattern rather than the solutions here.

-

因为五年后您仍然没有正确的答案,让我给

For you still don't have an accpted answer about five years later, let me give it a try(again) ..

我曾经想过好奇地重复使用模板模式作为一种解决方法,但是由于您将打开 BaseClass 进行继承,所以这不是一个好主意。您可能想看看先生。利珀特(Lippert)的博客文章,以更好地理解其原因。

I've ever thought about the Curiously Recurring Template Pattern as a workaround, but since you'll open BaseClass for inheritance it would not be a good idea. You might want to have a look at Mr. Lippert's blogpost for a better understanding of why.


  • 解决方案1 ​​:您不注册,我不认识..

  • Solution 1: You don't register, I don't recognize ..

public abstract class BaseClass {
    protected static void Register<U>(String identifier) where U : BaseClass {
        m_identities.Add(typeof(U).GetHashCode(), identifier);
    }

    public static String GetIdentifier<U>() where U : BaseClass {
        var t = typeof(U);
        var identifier = default(String);
        RuntimeHelpers.RunClassConstructor(t.TypeHandle);
        m_identities.TryGetValue(t.GetHashCode(), out identifier);
        return identifier;
    }

    static Dictionary<int, String> m_identities = new Dictionary<int, String> { };
}

public class DerivedClassA:BaseClass {
    static DerivedClassA() {
        BaseClass.Register<DerivedClassA>("12dc2490-065d-449e-a199-6ba051c93622");
    }
}

public class DerivedClassB:BaseClass {
    static DerivedClassB() {
        BaseClass.Register<DerivedClassB>("9745e24a-c38b-417d-a44d-0717e10e3b96");
    }
}






测试:


test:

Debug.Print("{0}", BaseClass.GetIdentifier<DerivedClassA>());
Debug.Print("{0}", BaseClass.GetIdentifier<DerivedClassB>());


这是通过类型初始化器。 Register 方法仅公开给派生类。并且 GetIdentifier Register 方法都被限制为使用从<$ c $派生的类型参数调用c> BaseClass 。尽管我们不强制派生类重写任何内容,但如果未注册自身,则 GetIdentifier 不能识别它并返回 null

This is is a relatively simple pattern through the type initializer. The Register method is only exposed to derived class; and both the GetIdentifier and Register methods are constrained to be invoked with a type argument which is derived from BaseClass. Although we don't force the derived classes to override anything, if it doesn't register itself, GetIdentifier doesn't recognize it and returns null.


  • 解决方案2 :在您显示身份之前,我为您提供了默认设置。只要您没有歧义,我相信您以为自己是谁。

  • Solution 2: Before you show your identity, I buy you a default. Whoever you think you are, I believe -- as long as there are no ambiguity.

public abstract class BaseClass {
    public abstract String Identifier {
        get;
    }

    public static Type GetDerivedClass(String identifier) {
        return m_aliases[identifier];
    }

    public static String GetIdentifier(Type t) {
        var value = default(String);

        if(t.IsSubclassOf(typeof(BaseClass))) {
            var key = t.GetHashCode();

            if(!m_identities.TryGetValue(key, out value)) {
                value=""+key;
                m_aliases.Add(value, t);
                m_identities[key]=value;
            }
        }

        return value;
    }

    static void UpdateAlias(BaseClass x) {
        var t = x.GetType();
        var value = x.Identifier;
        m_aliases.Add(value, t);
        m_identities[t.GetHashCode()]=value;
    }

    protected BaseClass() {
        BaseClass.UpdateAlias(this);
    }

    static Dictionary<String, Type> m_aliases = new Dictionary<String, Type> { };
    static Dictionary<int, String> m_identities = new Dictionary<int, String> { };
}







public class DerivedClassA:BaseClass {
    public override String Identifier {
        get {
            return "just text";
        }
    }
}

public class DerivedClassB:BaseClass {
    public override String Identifier {
        get {
            return "just text";
        }
    }
}






和测试:


and the test:

public static void TestMethod() {
    var idBeforeInstantiation = BaseClass.GetIdentifier(typeof(DerivedClassA));
    var y = new DerivedClassA { };
    var idAfterInstantiation = BaseClass.GetIdentifier(typeof(DerivedClassA));

    Debug.Print("B's: {0}", BaseClass.GetIdentifier(typeof(DerivedClassB)));
    Debug.Print("A's after: {0}", idAfterInstantiation);
    Debug.Print("A's before: {0}", idBeforeInstantiation);
    Debug.Print("A's present: {0}", BaseClass.GetIdentifier(typeof(DerivedClassA)));

    var type1 = BaseClass.GetDerivedClass(idAfterInstantiation);
    var type2 = BaseClass.GetDerivedClass(idBeforeInstantiation);

    Debug.Print("{0}", type2==type1); // true
    Debug.Print("{0}", type2==typeof(DerivedClassA)); // true
    Debug.Print("{0}", type1==typeof(DerivedClassA)); // true

    var typeB=BaseClass.GetDerivedClass(BaseClass.GetIdentifier(typeof(DerivedClassB)));

    var x = new DerivedClassB { }; // confilct
}


显然这是一个更复杂的解决方案。如您所见, idBeforeInstantiation idAfterInstantiation 是不同的,但是,它们都是的有效标识符DerivedClassA m_identities 包含每个派生类的最后更新的标识符,而 m_aliases 包含派生类的所有标识符别名。由于 virtual static 的组合当前不是该语言的功能(可能永远不会..),如果我们要强制执行 override ,则我们必须通过一些解决方法来做到这一点。如果您选择solution2,则您可能想实现自己的 UpdateAlias ,以防止派生类为单个类型提供过多的各种别名,尽管它们都是有效。故意放置测试中的最后一条语句以演示标识符的冲突。

Apparently this is a more complicated solution. As you can see idBeforeInstantiation and idAfterInstantiation are different, however, they are either valid identifiers for DerivedClassA. m_identities contains the last updated identifier for each derived class and m_aliases will contain all the identifier aliases for the derived classes. Since the combination of virtual and static is not a feature of the language currently(maybe never ..), if we want enforce the override then we have to do it through some workaround. If you'll choose solution2, You might want to implemenet you own UpdateAlias to prevent the derived classes from providing too much of various aliases for a single type, though they will all be valid. The last statement in the test are put deliberately to demonstrate the conflict of identifiers.

这两种解决方案都是为您考虑不要实例化派生类而精心设计的,它们都不是不需要 >那个。

For these two solutions are carefully designed for your consideration of not to instantiate the derived classes, none of them requires that.

这篇关于如何实现虚拟静态属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆