Domanda

E 'possibile costruire un oggetto con il suo costruttore interna all'interno di un metodo generico?

public abstract class FooBase { }

public class Foo : FooBase {
   internal Foo() { }
}

public static class FooFactory {
    public static TFooResult CreateFoo<TFooResult>()
    where TFooResult : FooBase, new() {
        return new TFooResult();
    }
}

risiede FooFactory nello stesso complesso come Foo. Classi chiamano il metodo factory in questo modo:

var foo = FooFactory.CreateFoo<Foo>();

Si ottiene l'errore di compilazione:

  

'Foo' deve essere un tipo non astratta con un costruttore senza parametri pubblico al fine di utilizzarlo come parametro 'TFooType' nel tipo generico o il metodo 'FooFactory.CreateFoo ()'

C'è un modo per aggirare questo?

Ho anche provato:

Activator.CreateInstance<TFooResult>(); 

Ciò solleva lo stesso errore in fase di esecuzione.

È stato utile?

Soluzione

Si potrebbe rimuovere il vincolo new() e ritorno:

//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true); 

anche se il cliente potrebbe fare anche questo. Questo, tuttavia, è incline a errori di runtime.

Questo è un problema difficile da risolvere in modo sicuro dal momento che la lingua non consente un costruttore declaraton astratta.

Altri suggerimenti

  

L'argomento di tipo deve avere un    pubblico senza parametri costruttore. Quando viene utilizzato insieme ad altri   vincoli, il nuovo) mosto vincolo (   specificare scorso.

http://msdn.microsoft.com/en-us/library /d5x73970.aspx

modifica: quindi no, se si utilizza nuovo vincolo (), non è possibile passare quella classe, se non si utilizza nuovo vincolo () si può provare a utilizzare la reflection per creare nuova istanza

public static TFooResult CreateFoo<TFooResult>()
where TFooResult : FooBase//, new()
        {
            return (TFooResult)typeof(TFooResult).GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] {}, null).Invoke(new object[]{});
            //return new TFooResult();
        }

Ci possono essere pochi work-around come qui sotto, ma non credo che si vuole andare in quel modo!

  • istruzione switch mettere dentro fabbrica che creerà l'istanza base sul tipo di parametro di tipo.

  • Ogni concreta attuazione FooBase si registrerà con FooFactory passando il metodo factory per creare è di per sé. Così FooFactory utilizzerà il dizionario interno

  • L'estensione sulla linea simile, tranne mappatura tra parametro di tipo e l'attuazione concreta sarebbe codice esterno (file XML, di configurazione, ecc). contenitori IOC / DI può anche aiuto qui.

public class GenericFactory
{
    public static T Create<T>(object[] args)
    {
        var types = new Type[args.Length];
        for (var i = 0; i < args.Length; i++)
            types[i] = args[i].GetType();

        return (T)typeof(T).GetConstructor(types).Invoke(args);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top