2014-09-29 11 views
9

Ho un tipo semplice con un convertitore di tipo personalizzato che viene compilato e caricato in fase di esecuzione. TypeDescriptor.GetConverter() però non trova il convertitore giusto. Ecco un esempio di stand-aloneTypeDescriptor.GetConverter() non restituisce il mio convertitore

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); 
     } 
    } 
} 

Ecco l'output dell'esempio (compilato in VS)

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

devo solo scavare l'attributo e creare l'istanza di me, o mi sto perdendo qualcos'altro qui?

ANCHE dispari! Quando viene eseguito in LINQPad come "programma C#", funziona davvero! ecco l'output. LINQPad ready source

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

Qualsiasi idea di cosa LINQPad realmente fa in modo diverso per farlo trovare il convertitore di destra?

+0

dovrebbe funzionare così, e [un test on-line rapido] (http://ideone.com/16utE6) mostra che lo fa. Puoi pubblicare un programma completo minimo che mostri il comportamento che descrivi? – hvd

+0

hmm, i tipi vengono compilati in fase di esecuzione, quindi questa deve essere la causa. eseguirò un esempio isolato –

+0

L'ho appena modificato per essere un esempio indipendente, ho dimenticato un commento di modifica: O –

risposta

8

.NET utilizza la riflessione per caricare il convertitore di tipi specificato. Quando si passa un'istanza Type a TypeConverterAttribute, il numero TypeConverterAttribute conterrà un nome di tipo qualificato per assembly. Il caricamento del nome di tipo qualificato dell'assembly non funziona, poiché l'assembly non può essere trovato. (Sì, anche se quell'assieme è già caricato.)

È possibile utilizzare il sovraccarico del costruttore che accetta una stringa per specificare il nome del tipo senza riferimenti all'assembly di definizione, nel qual caso verrà cercato nello stesso assemblaggio come il tipo di cui si sta richiedendo convertitore:

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

Nota: è anche possibile aggiungere convertitori di tipi in fase di esecuzione utilizzando TypeDescriptor.AddAttributes. Questo è utile se non puoi modificare il tipo, ad es. perché è un tipo di framework .NET. – Ananke

+0

Sono un tale idiota, stavo già usando questo concetto altrove per gli editor della griglia di proprietà, ma mi ha totalmente evitato –

+0

Questa risposta è stata estremamente utile. Per riferimento, ho dovuto utilizzare lo spazio dei nomi completo al posto di "LoadMe" per farlo funzionare. – DaveInCaz

Problemi correlati