C#如何构建表达式<;Func<;T、 U>&燃气轮机;对于对象的每个属性?

C#如何构建表达式<;Func<;T、 U>&燃气轮机;对于对象的每个属性?,c#,reflection,C#,Reflection,我有一个类FormBuilder,它有一个方法属性(Expression)。在构造函数中,我希望在获得TObject的所有属性后调用该方法。我该怎么做呢?我现在的代码是根据其他SO答案改编的,只会抛出错误,我不知道如何解决它们。这就是我到目前为止所做的: public abstract class FormBuilder<TObject> : FormBuilder { public FormBuilder() { // REPLICATE: Pro

我有一个类
FormBuilder
,它有一个方法
属性(Expression)
。在构造函数中,我希望在获得
TObject
的所有属性后调用该方法。我该怎么做呢?我现在的代码是根据其他SO答案改编的,只会抛出错误,我不知道如何解决它们。这就是我到目前为止所做的:

public abstract class FormBuilder<TObject> :
    FormBuilder {
    public FormBuilder() {
        //  REPLICATE: Property(p => p.NAME);

        var method = this.GetType().GetMethod("Property");
        var properties = typeof(TObject).GetProperties();

        var objectType = typeof(TObject);

        foreach (var p in properties) {
            var propertyType = p.GetType();

            var parameter = Expression.Parameter(propertyType, "p");
            var property = Expression.Property(parameter, p.Name);
            var @delegate = typeof(Func<,>).MakeGenericType(objectType, propertyType);

            //  throws: ParameterExpression of type 'System.Reflection.RuntimePropertyInfo'
            //  cannot be used for delegate parameter of type 'UserQuery+Command'
            var expression = Expression.Lambda(@delegate, property, new[] { parameter });

            //  method.MakeGenericMethod(parameter).Invoke(this, new[] { property });
        }
    }

    public FormPropertyBuilder<TProperty> Property<TProperty>(
        Expression<Func<TObject, TProperty>> expression) {
        var member = (expression.Body as MemberExpression).Member;
        var builder = new FormPropertyBuilder<TProperty>(member.Name);

        Properties.Add(builder);

        return builder;
    }
}
公共抽象类FormBuilder:
造模工{
公共表单生成器(){
//复制:属性(p=>p.NAME);
var method=this.GetType().GetMethod(“属性”);
var properties=typeof(TObject).GetProperties();
var objectType=typeof(TObject);
foreach(属性中的var p){
var propertyType=p.GetType();
var parameter=Expression.parameter(propertyType,“p”);
var property=Expression.property(参数,p.Name);
var@delegate=typeof(Func).MakeGenericType(objectType,propertyType);
//抛出:“System.Reflection.RuntimePropertyInfo”类型的ParameterExpression
//不能用于“UserQuery+Command”类型的委托参数
var expression=expression.Lambda(@delegate,property,new[]{parameter});
//MakeGenericMethod(parameter).Invoke(这是新的[]{property});
}
}
公共FormPropertyBuilder属性(
表达式(表达式){
var member=(expression.Body作为MemberExpression.member);
var builder=new-FormPropertyBuilder(member.Name);
添加(生成器);
返回生成器;
}
}
编辑

public sealed class CommandFormBuilder :
    FormBuilder<Command> {
    public CommandFormBuilder() {
        Property(
            p => p.SourceOfLoss).HasLabel("Source of Loss");
    }
}
公共密封类CommandFormBuilder:
造模工{
公共命令FormBuilder(){
财产(
p=>p.SourceOfLoss)。HasLabel(“损失来源”);
}
}
这是我通常调用方法的方式,但我需要在为每个属性构造时立即调用它

我的最终目标是通过该方法简单地为所有属性设定种子,并在以后必要时对其进行进一步配置。谢谢你的帮助

我回来了

在@Nkosi最后一次评论之后,我回到绘图板,从头开始。我对泛型太着迷了,一旦我稍微退一步,我就想出了如何得到我想要的。不能说这是最合适的方式,但现在我已经将它应用到了我的整个应用程序中,它似乎起到了作用。最后,我为特定任务制作了多个构建器(模板构建器?),比如表单、表格和PDF文档。这是我想到的。我将只展示FormBuilder,因为它对所有其他构建器几乎都是重复的,除了针对其场景的专用方法。这是自我发布问题以来经过多次迭代后的当前版本。哦,这个项目是在VS2013中为C#5构建的,所以一旦升级到新版本,可能会有改进

行动

public interface IFormActionBuilder {
    IFormActionBuilder HasFormId(
        string formId);

    IFormActionBuilder HasLabel(
        string label);

    IFormActionBuilder IsDefault();

    IFormActionBuilder IsFileUpload();
}

public interface IFormActionMetadata {
    string Controller { get; }
    bool Default { get; }
    string FormId { get; }
    string Enctype { get; }
    string Label { get; }
    string Name { get; }
}
public interface IFormGroupBuilder {
    IFormGroupBuilder HasOrder(
        short order);
}

public interface IFormGroupMetadata {
    string Label { get; }
    short Order { get; }
}
public interface IFormPropertyBuilder {
    IFormPropertyBuilder HasFormat(
        string format);

    IFormPropertyBuilder HasLabel(
        string label);

    IFormPropertyBuilder HasOrder(
        short order);

    IFormPropertyBuilder HasType(
        FormFieldType type);

    IFormPropertyBuilder InGroup(
        string group);

    IFormPropertyBuilder IsHidden();

    IFormPropertyBuilder IsReadOnly();

    IFormPropertyBuilder IsRequired();
}

public interface IFormPropertyMetadata {
    string Format { get; }
    string Group { get; }
    bool IsIgnored { get; set; }
    string Label { get; }
    string Name { get; }
    short Order { get; }
    bool Required { get; }
    FormFieldType Type { get; }
}

public interface IFormActionBuilder {
    IFormActionBuilder HasFormId(
        string formId);

    IFormActionBuilder HasLabel(
        string label);

    IFormActionBuilder IsDefault();

    IFormActionBuilder IsFileUpload();
}

public interface IFormActionMetadata {
    string Controller { get; }
    bool Default { get; }
    string FormId { get; }
    string Enctype { get; }
    string Label { get; }
    string Name { get; }
}
public interface IFormGroupBuilder {
    IFormGroupBuilder HasOrder(
        short order);
}

public interface IFormGroupMetadata {
    string Label { get; }
    short Order { get; }
}
public interface IFormPropertyBuilder {
    IFormPropertyBuilder HasFormat(
        string format);

    IFormPropertyBuilder HasLabel(
        string label);

    IFormPropertyBuilder HasOrder(
        short order);

    IFormPropertyBuilder HasType(
        FormFieldType type);

    IFormPropertyBuilder InGroup(
        string group);

    IFormPropertyBuilder IsHidden();

    IFormPropertyBuilder IsReadOnly();

    IFormPropertyBuilder IsRequired();
}

public interface IFormPropertyMetadata {
    string Format { get; }
    string Group { get; }
    bool IsIgnored { get; set; }
    string Label { get; }
    string Name { get; }
    short Order { get; }
    bool Required { get; }
    FormFieldType Type { get; }
}
属性

public interface IFormActionBuilder {
    IFormActionBuilder HasFormId(
        string formId);

    IFormActionBuilder HasLabel(
        string label);

    IFormActionBuilder IsDefault();

    IFormActionBuilder IsFileUpload();
}

public interface IFormActionMetadata {
    string Controller { get; }
    bool Default { get; }
    string FormId { get; }
    string Enctype { get; }
    string Label { get; }
    string Name { get; }
}
public interface IFormGroupBuilder {
    IFormGroupBuilder HasOrder(
        short order);
}

public interface IFormGroupMetadata {
    string Label { get; }
    short Order { get; }
}
public interface IFormPropertyBuilder {
    IFormPropertyBuilder HasFormat(
        string format);

    IFormPropertyBuilder HasLabel(
        string label);

    IFormPropertyBuilder HasOrder(
        short order);

    IFormPropertyBuilder HasType(
        FormFieldType type);

    IFormPropertyBuilder InGroup(
        string group);

    IFormPropertyBuilder IsHidden();

    IFormPropertyBuilder IsReadOnly();

    IFormPropertyBuilder IsRequired();
}

public interface IFormPropertyMetadata {
    string Format { get; }
    string Group { get; }
    bool IsIgnored { get; set; }
    string Label { get; }
    string Name { get; }
    short Order { get; }
    bool Required { get; }
    FormFieldType Type { get; }
}
从技术上讲,操作、组和属性接口可以合并为一个接口,但我选择将它们拆分为方法和属性,以便在配置期间使用它们和提取元数据时保持intellisense的整洁

Builder

public interface IFormMetadata {
    IList<IFormActionMetadata> ActionMetadatas { get; }
    IList<IFormGroupMetadata> GroupMetadatas { get; }
    IList<IFormPropertyMetadata> PropertyMetadatas { get; }
}

public abstract class FormBuilder<TObject> :
    IFormMetadata {
    public IList<IFormActionMetadata> ActionMetadatas { get; private set; }
    public IList<IFormGroupMetadata> GroupMetadatas { get; private set; }
    public IList<IFormPropertyMetadata> PropertyMetadatas { get; private set; }

    protected FormBuilder() {
        ActionMetadatas = new List<IFormActionMetadata>();
        GroupMetadatas = new List<IFormGroupMetadata> {
            new GroupBuilder()
        };
        PropertyMetadatas = typeof(TObject).GetProperties().Select(
            p => new PropertyBuilder(p.Name)).Cast<IFormPropertyMetadata>().ToList();
    }

    public IFormActionBuilder Action<TController>(
        Expression<Action<TController>> action)
        where TController : IController {
        var method = ((MethodCallExpression)action.Body).Method;
        var controller = typeof(TController).Name.Replace("Controller", null);
        var builder = new ActionBuilder(method.Name, controller);

        ActionMetadatas.Add(builder);

        return builder;
    }

    public IFormGroupBuilder Group(
        string label) {
        var builder = new GroupBuilder(label);

        GroupMetadatas.Add(builder);

        return builder;
    }

    public void Ignore<TProperty>(
        Expression<Func<TObject, TProperty>> expression) {
        var member = ((MemberExpression)expression.Body).Member;
        var propertyMetadata = PropertyMetadatas.SingleOrDefault(
            b => b.Name == member.Name);

        if (propertyMetadata == null) {
            return;
        }

        propertyMetadata.IsIgnored = true;
    }

    protected static T Placeholder<T>() {
        return default(T);
    }

    public IFormPropertyBuilder Property<TProperty>(
        Expression<Func<TObject, TProperty>> expression) {
        var member = ((MemberExpression)expression.Body).Member;

        return PropertyMetadatas.Single(
            b => b.Name == member.Name) as IFormPropertyBuilder;
    }

    public sealed class ActionBuilder :
        IFormActionBuilder,
        IFormActionMetadata {
        public string Controller { get; private set; }
        public bool Default { get; private set; }
        public string Enctype { get; private set; }
        public string FormId { get; private set; }
        public string Label { get; private set; }
        public string Name { get; private set; }

        public ActionBuilder(
            string action,
            string controller) {
            Controller = controller;
            Enctype = "application/x-www-form-urlencoded";
            FormId = "panel-form";
            Label = "Save";
            Name = action;
        }

        public IFormActionBuilder HasFormId(
            string formId) {
            FormId = formId;

            return this;
        }

        public IFormActionBuilder HasLabel(
            string label) {
            Label = label;

            return this;
        }

        public IFormActionBuilder IsDefault() {
            Default = true;

            return this;
        }

        public IFormActionBuilder IsFileUpload() {
            Enctype = "multipart/form-data";

            return this;
        }
    }

    public sealed class GroupBuilder :
        IFormGroupBuilder,
        IFormGroupMetadata {
        public string Label { get; private set; }
        public short Order { get; private set; }

        public GroupBuilder() {
        }

        public GroupBuilder(
            string label) {
            Label = label;
        }

        public IFormGroupBuilder HasOrder(
            short order) {
            Order = order;

            return this;
        }
    }

    public sealed class PropertyBuilder :
        IFormPropertyBuilder,
        IFormPropertyMetadata {
        private static readonly Type StringType;

        static PropertyBuilder() {
            StringType = typeof(string);
        }

        public string Format { get; private set; }
        public string Group { get; private set; }
        public bool IsIgnored { get; set; }
        public string Label { get; private set; }
        public string Name { get; private set; }
        public short Order { get; private set; }
        public bool Required { get; private set; }
        public FormFieldType Type { get; private set; }

        public PropertyBuilder(
            string name) {
            Name = name;
            Order = short.MaxValue;
            Required = !IsNullable(name);
            Type = FormFieldType.Text;
        }

        public IFormPropertyBuilder HasFormat(
            string format) {
            Format = format;

            return this;
        }

        public IFormPropertyBuilder HasLabel(
            string label) {
            Label = label;

            return this;
        }

        public IFormPropertyBuilder HasOrder(
            short order) {
            Order = order;

            return this;
        }

        public IFormPropertyBuilder HasType(
            FormFieldType type) {
            Type = type;

            return this;
        }

        public IFormPropertyBuilder InGroup(
            string group) {
            Group = group;

            return this;
        }

        public IFormPropertyBuilder IsHidden() {
            Type = FormFieldType.Hidden;

            return this;
        }

        private static bool IsNullable(
            string name) {
            var type = typeof(TObject).GetProperty(name).PropertyType;

            if (type == StringType) {
                return true;
            }

            return type.IsValueType
                && Nullable.GetUnderlyingType(type) != null;
        }

        public IFormPropertyBuilder IsReadOnly() {
            Type = FormFieldType.None;

            return this;
        }

        public IFormPropertyBuilder IsRequired() {
            Required = true;

            return this;
        }
    }
}
public static class FormLoader {
    private static IDictionary<Type, Builder> _builders;

    public static IFormMetadata Get<TObject>() {
        return Get(typeof(TObject));
    }

    public static IFormMetadata Get(
        Type type) {
        var builder = _builders[type];

        if (builder.Instance == null) {
            builder.Instance = Activator.CreateInstance(builder.Type) as IFormMetadata;
        }

        return builder.Instance;
    }

    public static void Initialize() {
        Initialize(Assembly.GetExecutingAssembly());
    }

    public static void Initialize(
        params Assembly[] assemblies) {
        var type = typeof(FormBuilder<>);

        _builders = assemblies.SelectMany(
            a => a.GetTypes()).Where(
            t =>
                !t.IsAbstract
                && !t.IsInterface
                && t.BaseType != null
                && t.BaseType.IsGenericType
                && t.BaseType.GetGenericTypeDefinition() == type).Select(
            t => new {
                ObjectType = t.BaseType.GetGenericArguments()[0],
                BuilderType = t
            }).ToDictionary(
            k => k.ObjectType,
            v => new Builder {
                Type = v.BuilderType
            });
    }

    private sealed class Builder {
        public IFormMetadata Instance { get; set; }
        public Type Type { get; set; }
    }
}
公共接口元数据{
IList ActionMetadatas{get;}
IList GroupMetadatas{get;}
IList PropertyMetadata{get;}
}
公共抽象类FormBuilder:
格式元数据{
公共IList ActionMetadatas{get;private set;}
public IList GroupMetadatas{get;private set;}
公共IList属性元数据{get;private set;}
受保护的FormBuilder(){
ActionMetadatas=新列表();
GroupMetadatas=新列表{
新的GroupBuilder()
};
PropertyMetadata=typeof(TObject).GetProperties()。选择(
p=>newpropertybuilder(p.Name)).Cast().ToList();
}
公共行动建设者行动(
表达(行动)
其中t控制器:i控制器{
var method=((MethodCallExpression)action.Body).method;
var controller=typeof(TController).Name.Replace(“controller”,null);
var builder=新的ActionBuilder(方法名称、控制器);
ActionMetadatas.Add(生成器);
返回生成器;
}
公共分组生成器组(
字符串标签){
var builder=新的GroupBuilder(标签);
GroupMetadatas.Add(生成器);
返回生成器;
}
公共无效忽略(
表达式(表达式){
var member=((MemberExpression)expression.Body).member;
var propertyMetadata=propertyMetadata.SingleOrDefault(
b=>b.Name==member.Name);
如果(propertyMetadata==null){
返回;
}
propertyMetadata.IsIgnored=true;
}
受保护的静态T占位符(){
返回默认值(T);
}
公共属性生成器属性(
表达式(表达式){
var member=((MemberExpression)expression.Body).member;
返回PropertyMetadata.Single(
b=>b.Name==member.Name)作为IFormPropertyBuilder;
}
公共密封类ActionBuilder:
ActionBuilder,
IFormActionMetadata{
公共字符串控制器{get;private set;}
公共bool默认值{get;private set;}
公共字符串类型{get;private set;}
公共字符串FormId{get;private set;}
公共字符串标签{get;private set;}
公共字符串名称{get;private set;}
公共行动建设者(
弦作用,
字符串控制器){
控制器=控制器;
Enctype=“application/x-www-form-urlencoded”;
FormId=“面板形式”;
Label=“保存”;