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

C# 在C中将类成员称为枚举#,c#,.net,reflection,metadata,C#,.net,Reflection,Metadata,是否有方法将类“成员”作为一级值传递 public class Bike { public Color BikeColour { get; set; } public bool IsGirlsBike { get; set; } } 然后我想引用字段名,而不涉及任何对象的概念 我想我想要的是一个枚举: public enum BikeFields {BikeColour, IsGirlsBike}; 但没有明确定义它 有没有办法在C#中做到这一点 编辑:为如此含糊道歉;我希

是否有方法将类“成员”作为一级值传递

public class Bike {
    public Color BikeColour { get; set; }
    public bool  IsGirlsBike { get; set; }
}
然后我想引用字段名,而不涉及任何对象的概念

我想我想要的是一个枚举:

public enum BikeFields {BikeColour, IsGirlsBike};
但没有明确定义它

有没有办法在C#中做到这一点

编辑:为如此含糊道歉;我希望能够将类成员称为第一类事物(几乎像绑定类型)


我想我可以用反射来实现这一点,但我希望它们在编译时被限定…

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

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);
var props=GetAllProperties()
。除了(新[]{GetProperty(x=>x.bikeColor)});
画(自行车、道具);

public IEnumerable GetAllProperties()
{
返回typeof(T).GetProperties();
}
公共属性信息GetProperty(表达式expr)
{
var uExpr=expr.Body作为一元表达式;
var memberExpr=uExpr。操作数作为MemberExpression;
返回memberExpr.Member作为PropertyInfo;
}
公共字典GetValues(T对象、IEnumerable道具)
{
返回props.ToDictionary(p=>p.Name,p=>p.GetValue(obj,null));
}
虚线绘制(自行车b,IEnumerable属性)
{
var值=GetValues(b,属性);
}

静态类型的枚举不能与类同时使用,因为它们是在同一步骤中编译的。因此,您需要两个步骤,第一步是创建类,然后生成相应的枚举。分两步实现这一目标的一种方法是使用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 : ","#>
<#
        }
#>
    }
<#
    }
#>
}
1。创建一个类库(我们称之为类库)。这将包含你的自行车课程

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 : ","#>
<#
        }
#>
    }
<#
    }
#>
}

构建类库,然后右键单击模板并单击“运行自定义工具”。在
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));
        }
    }
}

您将如何在代码中使用它们?您试图解决的问题是什么,这个“枚举”将是解决方案的一部分?目前这只是有点太抽象了。您已将其标记为反射,因此我假设您知道反射可能会带来什么(例如,
MemberInfo
)您的问题在当前形式下毫无意义。需要更多详细信息。请参阅已编辑的问题-如上所述,您可以使用反射获取属性的名称,然后与EnumBuilder结合,动态创建枚举(请参阅),然后呢?这不是一个真正的枚举,它做的事情与枚举不同。OP说,
我想我想要的是类似于枚举的东西,所以他不确定。我展示了动态的方式。有什么问题吗?是的@EZI-像这样的。。。但是编译时被检查了。请看编辑后的问题。谢谢@EZI-GetProperty非常有趣;除了nameof()之外,这里提出的所有答案都是运行时的,也就是说,如果不运行程序,就无法检查它们。我希望这是有意义的,tomab下面的答案与我的想法最接近-这些信息保存在编译器的某个地方-但我怀疑它被丢弃了。如果不能使用C#6.0,使用
nameof
可能是不可能的。谢谢@tomab,这是与我所想的最接近的解决方案——我希望编译器通过编程语言对用户更开放一点。
<#@ 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
    }
}
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));