据我所知C#
不支持虚拟静态属性。如何实现这样的行为C#
?
我想实现基类的所有派生类都必须重写静态属性。获取派生类型,我想访问一个名为的静态属性Identifier
Type t = typeof(DerivedClass);
var identifier= (String) t.GetProperty("Identifier", BindingFlags.Static).GetValue(null, null);
对于有同样想法并通过谷歌搜索找到这篇文章的人,请考虑抽象工厂模式 https://en.wikipedia.org/wiki/Abstract_factory_pattern而不是这里的解决方案。
--
因为大约五年后你仍然没有一个可以接受的答案,让我(再次)尝试一下..
我曾经想过奇怪的重复模板模式 https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern作为解决方法,但因为你会打开BaseClass
对于继承来说这不是一个好主意。您可能想看看Lippert 先生的博文 https://blogs.msdn.microsoft.com/ericlippert/2011/02/03/curiouser-and-curiouser/为了更好地理解原因。
-
解决方案1: 你不注册,我不认识..
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
and Register
方法被限制为使用派生自的类型参数来调用BaseClass
。虽然我们不强制派生类重写任何内容,但如果它没有注册自己,GetIdentifier
无法识别并返回null
.
-
解决方案2:在你表明身份之前,我给你买个默认的。无论你认为你是谁,我都相信——只要没有歧义。
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";
}
}
}
和测试:
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
and idAfterInstantiation
是不同的,但是,它们要么是有效的标识符DerivedClassA
. m_identities
包含每个派生类的最后更新的标识符,并且m_aliases
将包含派生类的所有标识符别名。自从组合virtual and static不是当前语言的功能(也许永远不会..),如果我们想强制执行override那么我们必须通过一些解决方法来做到这一点。如果您选择解决方案2,您可能想要实现您自己的UpdateAlias
以防止派生类为单一类型提供过多的各种别名,尽管它们都是有效的。测试中的最后一条语句是故意放置的,以演示标识符冲突。
这两种解决方案都是为您精心设计的考虑不实例化派生类,没有一个requires that.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)