【问题标题】:TypeDescriptor.GetConverter() doesnt return my converterTypeDescriptor.GetConverter() 不返回我的转换器
【发布时间】:2014-09-29 21:28:37
【问题描述】:

我有一个简单的类型,它带有一个在运行时编译和加载的自定义类型转换器。 TypeDescriptor.GetConverter() 虽然找不到正确的转换器。这是一个独立的例子

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

public class Program
{
    private static string src =
@"
using System;
using System.ComponentModel;
namespace LoadMe
{
    [TypeConverter(typeof(FooConverter))]
    public class Foo
    {
    }
    public class FooConverter : TypeConverter
    {
        // stuff
    }
}
";
    public static void Main()
    {
        var codeProvider        = new CSharpCodeProvider(new     Dictionary<string, string>{{ "CompilerVersion", "v4.0" }});
        var compileParameters   = new CompilerParameters(new[] { "System.dll"     }) { GenerateInMemory = true };
        var compilerResults     = codeProvider.CompileAssemblyFromSource(compileParameters, src);

        if (compilerResults.Errors.Count == 0)
        {
            var fooType = compilerResults.CompiledAssembly.GetType("LoadMe.Foo");
            Console.WriteLine(fooType.FullName + "::" + fooType.Assembly.FullName);
            Console.WriteLine("Type converter type = '" + TypeDescriptor.GetConverter(fooType).GetType().FullName + "'");
        }
        else 
        {
            foreach (var err in compilerResults.Errors)
                Console.WriteLine(err);
        }
    }
}

这里是例子的输出(用vs编译)

LoadMe.Foo::q5sszdls, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Type converter type = 'System.ComponentModel.TypeConverter'

我应该自己挖掘属性并创建实例,还是我在这里遗漏了其他东西?

也很奇怪!当在 LINQPad 中作为“C# 程序”运行时,它确实有效!这是输出。 LINQPad ready source

LoadMe.Foo::oqmid5in, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Type converter type = 'LoadMe.FooConverter'

知道 LINQPad 实际上做了什么不同的事情来让它找到合适的转换器吗?

【问题讨论】:

  • 它应该是这样工作的,a quick online test 表明它确实如此。你能发布一个最小的完整程序来演示你描述的行为吗?
  • 嗯,类型是在运行时编译的,所以这一定是原因。将掀起一个孤立的例子
  • 我只是将它编辑为一个独立的示例,忘记了编辑注释:O
  • 在这里查看解决方案:stackoverflow.com/a/7052397/2455604 - 我们使用了它,只需连接另一个 AssemblyResolver 就可以很好地工作。

标签: c# .net reflection typedescriptor


【解决方案1】:

.NET 使用反射来加载指定的类型转换器。当您将Type 实例传递给TypeConverterAttribute 时,您的TypeConverterAttribute 将包含一个程序集限定的类型名称。加载该程序集限定的类型名称不起作用,因为找不到该程序集。 (是的,即使该程序集已经加载。)

您可以使用带有字符串的构造函数重载来指定类型名称,而无需对定义程序集的任何引用,在这种情况下,它将在与您请求其转换器的类型相同的程序集中查找:

[TypeConverter("LoadMe.FooConverter")]
public class Foo
{
}

【讨论】:

  • 注意:您还可以在运行时使用 TypeDescriptor.AddAttributes 添加类型转换器。如果您无法修改类型,这很有用,例如因为它是 .NET 框架类型。
  • 我真是个白痴,我已经在其他地方将这个概念用于属性网格编辑器,但它完全避开了我
  • 这个答案非常有帮助。作为参考,我必须使用完全限定的命名空间来代替“LoadMe”才能工作。
  • @DaveInCaz 是的。 LoadMe 是 OP 使用的完全限定命名空间。
猜你喜欢
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 2023-03-05
  • 1970-01-01
相关资源
最近更新 更多