在 C# 中将 class 成员引用为枚举
Referring to class members as enumerations in C#
有没有办法将 class 'members' 作为第一个 class 值传递?
public class Bike {
public Color BikeColour { get; set; }
public bool IsGirlsBike { get; set; }
}
然后我想引用字段名称,而没有任何对象的概念。
我想我想要的是枚举之类的东西:
public enum BikeFields {BikeColour, IsGirlsBike};
但没有明确定义。
有没有办法在 C# 中执行此操作?
编辑:抱歉含糊不清;我希望能够引用 class 成员作为第一个 class 事物(几乎像绑定类型)。
Set<Bike:T> whichFieldsHaveBeenDrawn = new Set<Bike:T>();
Bike:T 未定义,希望下图能清楚说明这种新类型的工作原理。
whichFieldsHaveBeenDrawn.Include(Bike.BikeColour);
var remainingFields = Set.Subtract(Bike.GetAllFields(), whichFieldsHaveBeenDrawn);
Bike b = new Bike();
foreach (var field in remainingFields) { Draw(field, b); }
我想我可以用反射来做到这一点,但我希望它们在编译时合格...
您可以将属性及其值转换为字典
var bike = new Bike() { BikeColour = Color.Red, IsGirlsBike = true };
var props = bike.GetType().GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(bike, null));
编辑
如果我没理解错的话,你想写这样的代码
var props = GetAllProperties<Bike>()
.Except(new[] { GetProperty<Bike>(x => x.BikeColour) });
Draw(bike, props);
public IEnumerable<PropertyInfo> GetAllProperties<T>()
{
return typeof(T).GetProperties();
}
public PropertyInfo GetProperty<T>(Expression<Func<T,object>> expr)
{
var uExpr = expr.Body as UnaryExpression;
var memberExpr = uExpr.Operand as MemberExpression;
return memberExpr.Member as PropertyInfo;
}
public Dictionary<string,object> GetValues<T>(T obj, IEnumerable<PropertyInfo> props)
{
return props.ToDictionary(p => p.Name, p => p.GetValue(obj, null));
}
void Draw(Bike b, IEnumerable<PropertyInfo> properties)
{
var values = GetValues(b, properties);
}
您不能同时拥有静态类型的枚举和 class,因为它们是在同一步骤中编译的。所以你需要两个步骤,第一步是让 class 然后生成相应的枚举。分两步实现此目的的一种方法是使用像这样的 t4 模板:
1. 创建一个 class 库(假设称为 ClassLibrary)。这将包含您的自行车 class.
2. 在控制台应用程序(或您可能需要的任何其他类型的项目)中添加一个 t4 文本模板,如下所示:
<#@ template debug="true" hostspecific="false" language="C#" #>
<#@ assembly name="$(TargetDir)\ClassLibrary.dll" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="ClassLibrary" #>
<#@ output extension=".generated.cs" #>
namespace SO_31801914
{
<#
var classes = new Type[] { typeof(ClassLibrary.Bike) };
foreach (var cls in classes)
{
#>
public enum <#=cls.Name#>Enum
{
<# var props = cls.GetProperties();
for (int i = 0 ; i < props.Length; i++)
{
var prop = props[i];
bool skipComma = false;
if (i == props.Length - 1)
{
skipComma = true;
}
#>
<#=prop.Name#><#=skipComma ? string.Empty : ","#>
<#
}
#>
}
<#
}
#>
}
结果将是:
namespace SO_31801914
{
public enum BikeEnum
{
BikeColour,
IsGirlsBike
}
}
构建类库,然后右键单击模板并单击 "Run custom tool"。在TemplateName.generated.cs
你会得到上面的结果。
只是把它扔在那里。但是如果你想通过名字直接引用成员...为什么不使用nameof呢?
class Foo
{
public int A { get; set; }
public int B { get; set; }
}
class Program
{
static void Main(string[] args)
{
var rendered = new List<string>();
if (!rendered.Contains(nameof(Foo.A)))
{
//Do something
rendered.Add(nameof(Foo.A));
}
}
}
如果你真的想要枚举:
public enum FooFields
{
A,
B
}
var enumA = Enum.Parse(typeof (FooFields), nameof(Foo.A));
有没有办法将 class 'members' 作为第一个 class 值传递?
public class Bike {
public Color BikeColour { get; set; }
public bool IsGirlsBike { get; set; }
}
然后我想引用字段名称,而没有任何对象的概念。
我想我想要的是枚举之类的东西:
public enum BikeFields {BikeColour, IsGirlsBike};
但没有明确定义。
有没有办法在 C# 中执行此操作?
编辑:抱歉含糊不清;我希望能够引用 class 成员作为第一个 class 事物(几乎像绑定类型)。
Set<Bike:T> whichFieldsHaveBeenDrawn = new Set<Bike:T>();
Bike:T 未定义,希望下图能清楚说明这种新类型的工作原理。
whichFieldsHaveBeenDrawn.Include(Bike.BikeColour);
var remainingFields = Set.Subtract(Bike.GetAllFields(), whichFieldsHaveBeenDrawn);
Bike b = new Bike();
foreach (var field in remainingFields) { Draw(field, b); }
我想我可以用反射来做到这一点,但我希望它们在编译时合格...
您可以将属性及其值转换为字典
var bike = new Bike() { BikeColour = Color.Red, IsGirlsBike = true };
var props = bike.GetType().GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(bike, null));
编辑
如果我没理解错的话,你想写这样的代码
var props = GetAllProperties<Bike>()
.Except(new[] { GetProperty<Bike>(x => x.BikeColour) });
Draw(bike, props);
public IEnumerable<PropertyInfo> GetAllProperties<T>()
{
return typeof(T).GetProperties();
}
public PropertyInfo GetProperty<T>(Expression<Func<T,object>> expr)
{
var uExpr = expr.Body as UnaryExpression;
var memberExpr = uExpr.Operand as MemberExpression;
return memberExpr.Member as PropertyInfo;
}
public Dictionary<string,object> GetValues<T>(T obj, IEnumerable<PropertyInfo> props)
{
return props.ToDictionary(p => p.Name, p => p.GetValue(obj, null));
}
void Draw(Bike b, IEnumerable<PropertyInfo> properties)
{
var values = GetValues(b, properties);
}
您不能同时拥有静态类型的枚举和 class,因为它们是在同一步骤中编译的。所以你需要两个步骤,第一步是让 class 然后生成相应的枚举。分两步实现此目的的一种方法是使用像这样的 t4 模板:
1. 创建一个 class 库(假设称为 ClassLibrary)。这将包含您的自行车 class.
2. 在控制台应用程序(或您可能需要的任何其他类型的项目)中添加一个 t4 文本模板,如下所示:
<#@ template debug="true" hostspecific="false" language="C#" #>
<#@ assembly name="$(TargetDir)\ClassLibrary.dll" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="ClassLibrary" #>
<#@ output extension=".generated.cs" #>
namespace SO_31801914
{
<#
var classes = new Type[] { typeof(ClassLibrary.Bike) };
foreach (var cls in classes)
{
#>
public enum <#=cls.Name#>Enum
{
<# var props = cls.GetProperties();
for (int i = 0 ; i < props.Length; i++)
{
var prop = props[i];
bool skipComma = false;
if (i == props.Length - 1)
{
skipComma = true;
}
#>
<#=prop.Name#><#=skipComma ? string.Empty : ","#>
<#
}
#>
}
<#
}
#>
}
结果将是:
namespace SO_31801914
{
public enum BikeEnum
{
BikeColour,
IsGirlsBike
}
}
构建类库,然后右键单击模板并单击 "Run custom tool"。在TemplateName.generated.cs
你会得到上面的结果。
只是把它扔在那里。但是如果你想通过名字直接引用成员...为什么不使用nameof呢?
class Foo
{
public int A { get; set; }
public int B { get; set; }
}
class Program
{
static void Main(string[] args)
{
var rendered = new List<string>();
if (!rendered.Contains(nameof(Foo.A)))
{
//Do something
rendered.Add(nameof(Foo.A));
}
}
}
如果你真的想要枚举:
public enum FooFields
{
A,
B
}
var enumA = Enum.Parse(typeof (FooFields), nameof(Foo.A));