C# 除了奇怪的重复模板模式,还有其他选择吗?
在过去的几周里,我对这种模式感到有些头疼 以下是我的两个问题:C# 除了奇怪的重复模板模式,还有其他选择吗?,c#,c#-4.0,static-methods,C#,C# 4.0,Static Methods,在过去的几周里,我对这种模式感到有些头疼 以下是我的两个问题: 如何改进以下示例: public class DocketType : Enumeration<DocketType, int, string> { public static DocketType Withdrawal = new DocketType(2, "Withdrawal"); public static DocketType Installation = new DocketType
public class DocketType : Enumeration<DocketType, int, string>
{
public static DocketType Withdrawal = new DocketType(2, "Withdrawal");
public static DocketType Installation = new DocketType(3, "Installation");
private DocketType(int docketTypeId, string description)
: base(docketTypeId, description) { }
}
正如您将从我的第二个链接问题中看到的,这个问题的问题是调用Enumeration.Resolve(X值)代码>不会导致实例化DocketType
静态对象
我并不反对完全从头重写。我知道这是一种很大的代码气味。目前,为了使其正常工作,我的基类具有受保护的静态方法ChildResolve
,并且我已将Resolve
添加到我的每个枚举类中。讨厌的东西
回答:
似乎没有很好的替代模式,因此我坚持使用该模式,并从公认的答案中汲取灵感,得出以下结论:
static Enumeration()
{
GetAll();
}
public static void GetAll()
{
var type = typeof(TEnum);
var fields = type.GetFields(BindingFlags.Public |
BindingFlags.Static | BindingFlags.DeclaredOnly);
foreach (var info in fields)
{
var locatedValue = info.GetValue(null) as Enumeration<TEnum, X, Y>;
Cache.Add(locatedValue.Value, locatedValue);
}
}
静态枚举()
{
GetAll();
}
公共静态void GetAll()
{
var类型=类型(TEnum);
var fields=type.GetFields(BindingFlags.Public |
BindingFlags.Static | BindingFlags.DeclaredOnly);
foreach(字段中的var信息)
{
var locatedValue=info.GetValue(null)作为枚举;
Cache.Add(locatedValue.Value,locatedValue);
}
}
这也是codecampservermvc示例项目中使用的相同代码,因此使用它我感觉不那么脏 您希望“对给定类型的所有子类”执行某些操作。如果不使用AppDomain.Current.GetAssemblies()并对其进行迭代,任何此类性质的操作都是不可能的。如果采用这种方法,可以通过创建仅应用于程序集(以及应包含在子类搜索中的其他程序集)的程序集级属性来优化性能,并在准备对每个程序集调用.GetTypes()时使用该属性
为了清楚起见,下面是一个获取所有这些子类的示例:
Type[] subclasses = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => Attribute.IsDefined(typeof(MyEnumeartionAssemblyAttribute)))
.SelectMany(x => x.GetTypes())
.Where(x => x.BaseType != null &&
x.BaseType.IsGenericType &&
x.BaseType.GetGenericTypeDefinition() == typeof(Enumeration<,,>));
Type[]subclass=AppDomain.CurrentDomain.getAssemblys()
.Where(x=>Attribute.IsDefined(typeof(MyEnumeartionAssemblyAttribute)))
.SelectMany(x=>x.GetTypes())
.Where(x=>x.BaseType!=null&&
x、 BaseType.IsGenericType&&
x、 BaseType.GetGenericTypeDefinition()==typeof(枚举));
从这里开始,在每个系统上使用反射应该是一个简单的问题。键入静态字段并执行您想要的操作。您需要将静态字段推送到一个类中,该类具有一个静态实例作为实例字段。这样,您就可以通过一个静态成员访问枚举,该静态成员立即引用所有枚举成员
一个快速组合的示例:
// The Collection of values to be enumerated
public class DocketEnum : EnumarationCollection<DocketType, int, string>
{
// Values are fields on a statically instanced version of this class
public DocketType Withdrawal = new DocketType(2, "Withdrawal");
public DocketType Installation = new DocketType(3, "Installation");
// The publicly accessible static enumeration
public static DocketEnum Values = new DocketEnum();
}
// The actual value class
public class DocketType : EnumerationValue<DocketType, int, string>
{
// Call through to the helper base constructor
public DocketType(int docketTypeId, string description)
: base(docketTypeId, description) { }
}
// Base class for the enumeration
public abstract class EnumarationCollection<TType, X, Y>
where TType : EnumerationValue<TType, X, Y>
{
// Resolve looks at the static Dictionary in the base helpers class
public TType Resolve(X value)
{
return Cache[value] as TType;
}
public static Dictionary<X, EnumerationValue<TType, X, Y> > Cache = new Dictionary<X, EnumerationValue<TType, X, Y>>();
}
// Base class for the value
public abstract class EnumerationValue<TType, X, Y>
where TType : EnumerationValue<TType, X, Y>
{
// helper constructer talks directly the the base helper class for the Enumeration
protected EnumerationValue(X value, Y displayName)
{
EnumarationCollection<TType, X,Y >.Cache.Add(value, this as TType);
}
}
class MainClass
{
public static void Main (string[] args)
{
// You can immediately resolve to the enumeration
Console.WriteLine(DocketEnum.Values.Resolve(2).ToString());
}
}
//要枚举的值的集合
公共类DocketEnum:EnumarationCollection
{
//值是此类的静态实例化版本上的字段
公共案卷类型撤回=新案卷类型(2,“撤回”);
公共DocketType安装=新DocketType(3,“安装”);
//可公开访问的静态枚举
公共静态DocketNum值=新DocketNum();
}
//实际值类
公共类DocketType:枚举值
{
//调用helper基构造函数
公共DocketType(int docketTypeId,字符串描述)
:base(docketTypeId,description){}
}
//枚举的基类
公共抽象类EnumarationCollection
其中TType:EnumerationValue
{
//Resolve查看基本helpers类中的静态字典
公共TType解析(X值)
{
将Cache[value]返回为TType;
}
公共静态字典缓存=新字典();
}
//值的基类
公共抽象类枚举值
其中TType:EnumerationValue
{
//helper构造函数直接与枚举的基helper类对话
受保护的枚举值(X值,Y显示名称)
{
EnumarationCollection.Cache.Add(值,此为TType);
}
}
类主类
{
公共静态void Main(字符串[]args)
{
//您可以立即解析为枚举
Console.WriteLine(docketnum.Values.Resolve(2.ToString());
}
}
它不是很优雅,但像这样的东西可能会奏效:
public class DocketType : Enumeration<DocketType, int, string>
{
public static readonly DocketType Withdrawal =
new DocketType(2, "Withdrawal");
public static readonly DocketType Installation =
new DocketType(3, "Installation");
private DocketType(int docketTypeId, string description)
: base(docketTypeId, description) { }
}
public abstract class Enumeration<TEnum, TId, TDescription> : IComparable
where TEnum : Enumeration<TEnum, TId, TDescription>
{
private static readonly Dictionary<TId, TEnum> _cache;
static Enumeration()
{
Type t = typeof(TEnum);
_cache = t.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(f => f.FieldType == t)
.Select(f => (TEnum)f.GetValue(null))
.ToDictionary(e => e.Id, e => e);
}
public static TEnum Resolve(TId id)
{
return _cache[id];
}
public TId Id { get; private set; }
public TDescription Description { get; private set; }
protected Enumeration(TId id, TDescription description)
{
Id = id;
Description = description;
}
// IComparable
public int CompareTo(object obj)
{
// TODO
throw new NotImplementedException();
}
}
公共类DocketType:枚举
{
公共静态只读DocketType撤回=
新的案卷类型(2,“撤回”);
公共静态只读DocketType安装=
新的文件类型(3,“安装”);
私有DocketType(int docketTypeId,字符串描述)
:base(docketTypeId,description){}
}
公共抽象类枚举:IComparable
其中TEnum:枚举
{
专用静态只读字典\u缓存;
静态枚举()
{
t型=类型(10μm);
_cache=t.GetFields(BindingFlags.Public | BindingFlags.Static)
.其中(f=>f.FieldType==t)
.选择(f=>(十微米)f.GetValue(null))
.ToDictionary(e=>e.Id,e=>e);
}
公共静态TEnum解析(TId id)
{
返回_缓存[id];
}
公共TId Id{get;private set;}
公共TDdescription Description{get;private set;}
受保护枚举(TId id、TDDescription描述)
{
Id=Id;
描述=描述;
}
//不可比
公共整数比较(对象对象对象)
{
//待办事项
抛出新的NotImplementedException();
}
}
如果您确实想强制另一个类的静态构造函数运行,可以使用。您可以从枚举的静态构造函数调用它
,以便在您第一次对泛型类型的任何实例化使用静态方法时运行它:
static Enumeration()
{
RuntimeHelpers.RunClassConstructor(typeof(TEnum).TypeHandle);
}
+1是一个非常好的主意,但我不希望有额外的值实例。我已经没有了
static Enumeration()
{
RuntimeHelpers.RunClassConstructor(typeof(TEnum).TypeHandle);
}