给定一组属性,如何确定最匹配的构造函数
How to determine the best-matched constructor, given a set of properties
虽然可以通过反射查询应用于任何 class 的属性,但无法确定在编译时调用了哪个构造函数重载。在我的场景中,我正在分析一个程序集中的所有类型,这些类型具有如下应用的属性 [TestAttribute]
。
[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
public class TestAttribute: Attribute
{
public string Name { get; } = "";
public string NameDisplay { get; } = "";
public string Description { get; set; } = "";
public TestAttribute () { }
public TestAttribute (string name) { this.Name = name; }
public TestAttribute (string name, string nameDisplay) : this (name) { this.NameDisplay = nameDisplay; }
public TestAttribute (string name, string nameDisplay, string description) : this (name, nameDisplay) { this.Description = description; }
}
[TestAttribute()]
[TestAttribute ("_Name")]
[TestAttribute ("_Name_", "_NameDisplay_")]
[TestAttribute ("_Name_", "_NameDisplay_", "_Description_")]
public class TestClass { }
objective 用于生成声明 class TestClass
并应用正确属性的代码,并将其发送到新程序集中。现在,由于属性声明语法丢失到运行时,我只能查询属性特性。但是,请注意某些特性属性如何没有设置器。此外,构造函数参数的名称和顺序与它们设置的内部属性之间没有关联。
var type = typeof (TestClass);
var attributes = type.GetCustomAttributes(typeof(TestAttribute), inherit: false).Cast<Attribute>();
foreach (var attribute in attributes)
{
var attributeType = attribute.GetType();
var constructors = attributeType.GetConstructors().OrderByDescending (c => c.GetParameters().Length);
var attributeName = attributeType.Name.Substring (0, attributeType.Name.Length - nameof (Attribute).Length);
var properties = attributeType
.GetProperties (BindingFlags.Instance | BindingFlags.Public)
.Where (p => p.CanRead)
.Where (p => p.GetGetMethod (nonPublic: false) != null)
.Where (p => ((p.PropertyType.IsValueType) || (p.PropertyType == typeof (string))))
.ToList();
foreach (var constructor in constructors)
{
var parameters = constructor.GetParameters().ToList();
if (parameters.Any())
{
// Should write: [TestAttribute ("_Name_", "_NameDisplay_", "_Description_")]
Console.WriteLine($@"[{attributeName} (???????)]");
}
else
{
// Correct.
Console.WriteLine($@"[{attributeName}]");
}
}
}
缺少通过错误处理尝试所有排列的粗暴方法,我如何可靠地重新创建代码如下:
[TestAttribute()]
[TestAttribute ("_Name")]
[TestAttribute ("_Name_", "_NameDisplay_")]
[TestAttribute ("_Name_", "_NameDisplay_", "_Description_")]
public class TestClass { }
如有任何建议,我们将不胜感激。
System.Reflection.CustomAttributeData
class 提供有关使用的构造函数、CustomAttributes 的命名和位置参数的信息。
您可以使用 CustomAttributeData.GetCustomAttributes(...)
或 typeof(...).GetCustomAttributesData()
作为起点。
虽然可以通过反射查询应用于任何 class 的属性,但无法确定在编译时调用了哪个构造函数重载。在我的场景中,我正在分析一个程序集中的所有类型,这些类型具有如下应用的属性 [TestAttribute]
。
[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
public class TestAttribute: Attribute
{
public string Name { get; } = "";
public string NameDisplay { get; } = "";
public string Description { get; set; } = "";
public TestAttribute () { }
public TestAttribute (string name) { this.Name = name; }
public TestAttribute (string name, string nameDisplay) : this (name) { this.NameDisplay = nameDisplay; }
public TestAttribute (string name, string nameDisplay, string description) : this (name, nameDisplay) { this.Description = description; }
}
[TestAttribute()]
[TestAttribute ("_Name")]
[TestAttribute ("_Name_", "_NameDisplay_")]
[TestAttribute ("_Name_", "_NameDisplay_", "_Description_")]
public class TestClass { }
objective 用于生成声明 class TestClass
并应用正确属性的代码,并将其发送到新程序集中。现在,由于属性声明语法丢失到运行时,我只能查询属性特性。但是,请注意某些特性属性如何没有设置器。此外,构造函数参数的名称和顺序与它们设置的内部属性之间没有关联。
var type = typeof (TestClass);
var attributes = type.GetCustomAttributes(typeof(TestAttribute), inherit: false).Cast<Attribute>();
foreach (var attribute in attributes)
{
var attributeType = attribute.GetType();
var constructors = attributeType.GetConstructors().OrderByDescending (c => c.GetParameters().Length);
var attributeName = attributeType.Name.Substring (0, attributeType.Name.Length - nameof (Attribute).Length);
var properties = attributeType
.GetProperties (BindingFlags.Instance | BindingFlags.Public)
.Where (p => p.CanRead)
.Where (p => p.GetGetMethod (nonPublic: false) != null)
.Where (p => ((p.PropertyType.IsValueType) || (p.PropertyType == typeof (string))))
.ToList();
foreach (var constructor in constructors)
{
var parameters = constructor.GetParameters().ToList();
if (parameters.Any())
{
// Should write: [TestAttribute ("_Name_", "_NameDisplay_", "_Description_")]
Console.WriteLine($@"[{attributeName} (???????)]");
}
else
{
// Correct.
Console.WriteLine($@"[{attributeName}]");
}
}
}
缺少通过错误处理尝试所有排列的粗暴方法,我如何可靠地重新创建代码如下:
[TestAttribute()]
[TestAttribute ("_Name")]
[TestAttribute ("_Name_", "_NameDisplay_")]
[TestAttribute ("_Name_", "_NameDisplay_", "_Description_")]
public class TestClass { }
如有任何建议,我们将不胜感激。
System.Reflection.CustomAttributeData
class 提供有关使用的构造函数、CustomAttributes 的命名和位置参数的信息。
您可以使用 CustomAttributeData.GetCustomAttributes(...)
或 typeof(...).GetCustomAttributesData()
作为起点。