使用 Reflection.Emit 将自定义属性复制到另一个方法

发布于 2024-08-23 07:49:02 字数 158 浏览 13 评论 0原文

我正在尝试根据现有接口生成一组新的 wcf 接口。 我正在使用 Reflection.Emit 命名空间来完成此任务。我的问题是如何将旧的自定义属性从一种方法复制到新方法。我见过的 SetCustomAttributes() 的每个示例都需要事先了解属性类型。我需要在运行时发现属性类型。有什么想法吗?

I am trying to generate a new set of wcf interfaces based on existing interfaces.
I am using the Reflection.Emit namespace to accomplish this. My problem is how to copy the old custom attributes from one method to the new method. Every example I have seen of SetCustomAttributes() requires knowing the attribute type beforehand. I need to discover the attribute type at runtime. Any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白鸥掠海 2024-08-30 07:49:02

您(frjames)发布的答案很接近,但没有考虑像...这样的属性初始值设定项。

[ServiceBehavior(Name="ServiceName")]

但是,将 CustomAttributeData 转换为 CustomAttributeBuilder 以在 Reflection.Emit 中使用的想法是正确的。

我最终不得不为一个开源项目(Autofac)执行此操作,并提出了这种扩展方法:

public static CustomAttributeBuilder ToAttributeBuilder(this CustomAttributeData data)
{
  if (data == null)
  {
    throw new ArgumentNullException("data");
  }

  var constructorArguments = new List<object>();
  foreach (var ctorArg in data.ConstructorArguments)
  {
    constructorArguments.Add(ctorArg.Value);
  }

  var propertyArguments = new List<PropertyInfo>();
  var propertyArgumentValues = new List<object>();
  var fieldArguments = new List<FieldInfo>();
  var fieldArgumentValues = new List<object>();
  foreach (var namedArg in data.NamedArguments)
  {
    var fi = namedArg.MemberInfo as FieldInfo;
    var pi = namedArg.MemberInfo as PropertyInfo;

    if (fi != null)
    {
      fieldArguments.Add(fi);
      fieldArgumentValues.Add(namedArg.TypedValue.Value);
    }
    else if (pi != null)
    {
      propertyArguments.Add(pi);
      propertyArgumentValues.Add(namedArg.TypedValue.Value);
    }
  }
  return new CustomAttributeBuilder(
    data.Constructor,
    constructorArguments.ToArray(),
    propertyArguments.ToArray(),
    propertyArgumentValues.ToArray(),
    fieldArguments.ToArray(),
    fieldArgumentValues.ToArray());
}

该方法解释了初始化属性的所有方法。

The answer you (frjames) posted is close, but doesn't account for property initializers like...

[ServiceBehavior(Name="ServiceName")]

However, the idea of converting CustomAttributeData to a CustomAttributeBuilder for use in Reflection.Emit is right on.

I ended up having to do this for an open source project (Autofac) and came up with this extension method:

public static CustomAttributeBuilder ToAttributeBuilder(this CustomAttributeData data)
{
  if (data == null)
  {
    throw new ArgumentNullException("data");
  }

  var constructorArguments = new List<object>();
  foreach (var ctorArg in data.ConstructorArguments)
  {
    constructorArguments.Add(ctorArg.Value);
  }

  var propertyArguments = new List<PropertyInfo>();
  var propertyArgumentValues = new List<object>();
  var fieldArguments = new List<FieldInfo>();
  var fieldArgumentValues = new List<object>();
  foreach (var namedArg in data.NamedArguments)
  {
    var fi = namedArg.MemberInfo as FieldInfo;
    var pi = namedArg.MemberInfo as PropertyInfo;

    if (fi != null)
    {
      fieldArguments.Add(fi);
      fieldArgumentValues.Add(namedArg.TypedValue.Value);
    }
    else if (pi != null)
    {
      propertyArguments.Add(pi);
      propertyArgumentValues.Add(namedArg.TypedValue.Value);
    }
  }
  return new CustomAttributeBuilder(
    data.Constructor,
    constructorArguments.ToArray(),
    propertyArguments.ToArray(),
    propertyArgumentValues.ToArray(),
    fieldArguments.ToArray(),
    fieldArgumentValues.ToArray());
}

That one accounts for all the ways to initialize the attribute.

扬花落满肩 2024-08-30 07:49:02

这是我经过更多研究后得出的答案。

CustomAttributeBuilder ct = AddAttributesToMemberInfo(methodInfo);
if (ct != null)
{
    methodBuilder.SetCustomAttribute(ct);
}

CustomAttributeBuilder AddAttributesToMemberInfo(MemberInfo oldMember)
{
    CustomAttributeBuilder ct = null;
    IList<CustomAttributeData> customMethodAttributes = CustomAttributeData.GetCustomAttributes(oldMember);
    foreach (CustomAttributeData att in customMethodAttributes)
    {
        List<object> namedFieldValues = new List<object>();
        List<FieldInfo> fields = new List<FieldInfo>();
        List<object> constructorArguments = new List<object>();
        foreach (CustomAttributeTypedArgument cata in att.ConstructorArguments)
        {
            constructorArguments.Add(cata.Value);
        }
        if (att.NamedArguments.Count > 0)
        {
            FieldInfo[] possibleFields = att.GetType().GetFields();

            foreach (CustomAttributeNamedArgument cana in att.NamedArguments)
            {
                for (int x = 0; x < possibleFields.Length; x++)
                {
                    if (possibleFields[x].Name.CompareTo(cana.MemberInfo.Name) == 0)
                    {
                        fields.Add(possibleFields[x]);
                        namedFieldValues.Add(cana.TypedValue.Value);
                    }
                }


            }
        }

        if (namedFieldValues.Count > 0)
        {
            ct = new CustomAttributeBuilder(att.Constructor, constructorArguments.ToArray(), fields.ToArray(), namedFieldValues.ToArray());
        }
        else
        {
            ct = new CustomAttributeBuilder(att.Constructor, constructorArguments.ToArray());
        }


    }
    return ct;
}

Here is the answer I came up with after some more research.

CustomAttributeBuilder ct = AddAttributesToMemberInfo(methodInfo);
if (ct != null)
{
    methodBuilder.SetCustomAttribute(ct);
}

CustomAttributeBuilder AddAttributesToMemberInfo(MemberInfo oldMember)
{
    CustomAttributeBuilder ct = null;
    IList<CustomAttributeData> customMethodAttributes = CustomAttributeData.GetCustomAttributes(oldMember);
    foreach (CustomAttributeData att in customMethodAttributes)
    {
        List<object> namedFieldValues = new List<object>();
        List<FieldInfo> fields = new List<FieldInfo>();
        List<object> constructorArguments = new List<object>();
        foreach (CustomAttributeTypedArgument cata in att.ConstructorArguments)
        {
            constructorArguments.Add(cata.Value);
        }
        if (att.NamedArguments.Count > 0)
        {
            FieldInfo[] possibleFields = att.GetType().GetFields();

            foreach (CustomAttributeNamedArgument cana in att.NamedArguments)
            {
                for (int x = 0; x < possibleFields.Length; x++)
                {
                    if (possibleFields[x].Name.CompareTo(cana.MemberInfo.Name) == 0)
                    {
                        fields.Add(possibleFields[x]);
                        namedFieldValues.Add(cana.TypedValue.Value);
                    }
                }


            }
        }

        if (namedFieldValues.Count > 0)
        {
            ct = new CustomAttributeBuilder(att.Constructor, constructorArguments.ToArray(), fields.ToArray(), namedFieldValues.ToArray());
        }
        else
        {
            ct = new CustomAttributeBuilder(att.Constructor, constructorArguments.ToArray());
        }


    }
    return ct;
}
夏雨凉 2024-08-30 07:49:02

Travis Illig 的代码需要修改如下才能与 .Net Core 一起使用:

foreach (var namedArg in data.NamedArguments)
{
  string argName = namedArg.MemberName;
  var fi = data.AttributeType.GetField(argName);
  var pi = data.AttributeType.GetProperty(argName);

The code from Travis Illig needs amendment as below to work with .Net Core:

foreach (var namedArg in data.NamedArguments)
{
  string argName = namedArg.MemberName;
  var fi = data.AttributeType.GetField(argName);
  var pi = data.AttributeType.GetProperty(argName);
笑红尘 2024-08-30 07:49:02

试试这个:

MethodInfo mi;
//...
object[] custAttribs = mi.GetCustomAttributes(false);
foreach (object attrib in custAttribs)
   attrib.GetType();

我假设你有你的方法的 MethodInfo

try this:

MethodInfo mi;
//...
object[] custAttribs = mi.GetCustomAttributes(false);
foreach (object attrib in custAttribs)
   attrib.GetType();

i assume you have MethodInfo for your methods

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文