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=“保存”;