将类成员称为C#中的枚举

时间:2015-08-04 06:14:25

标签: c# .net reflection metadata

有没有办法将类'成员'作为第一类值传递?

public class Bike {
    public Color BikeColour { get; set; }
    public bool  IsGirlsBike { get; set; }
}

我想在没有任何对象概念的情况下引用字段名称。

我想我想要的就像枚举一样:

public enum BikeFields {BikeColour, IsGirlsBike};

但未明确定义。

有没有办法在C#中执行此操作?

编辑:抱歉这么模糊;我希望能够将类成员称为第一类(几乎像绑定类型)。

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); }

我想我可以用反射做到这一点,但我希望它们在编译时合格......

3 个答案:

答案 0 :(得分:2)

您不能与类同时使用静态类型的枚举,因为它们是在同一步骤中编译的。所以你需要两个步骤,首先是让类生成相应的枚举。通过两个步骤实现此目的的一种方法是使用这样的t4模板:

1。创建一个类库(让我们称之为ClassLibrary)。这将包含您的Bike类。

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
    }
}

构建ClassLibrary然后右键单击模板并单击&#34;运行自定义工具&#34;。在TemplateName.generated.cs中,您将获得上述结果。

答案 1 :(得分:1)

您可以将属性及其值转换为字典

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);
}

答案 2 :(得分:1)

把它扔到那里。但是如果你想直接通过名字引用成员......为什么不使用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));