Domanda

Io sicuramente ricordo di aver visto da qualche parte un esempio di farlo utilizzando la riflessione o qualcosa del genere. Era qualcosa che aveva a che fare con SqlParameterCollection che non è creabile da un utente (se non mi sbaglio). Purtroppo non riesce a trovare più.

Qualcuno può condividere questo trucco? Non che io considero un valido approccio in fase di sviluppo, sono solo molto interessati alla possibilità di fare questo.

È stato utile?

Soluzione

// the types of the constructor parameters, in order
// use an empty Type[] array if the constructor takes no parameters
Type[] paramTypes = new Type[] { typeof(string), typeof(int) };

// the values of the constructor parameters, in order
// use an empty object[] array if the constructor takes no parameters
object[] paramValues = new object[] { "test", 42 };

TheTypeYouWantToInstantiate instance =
    Construct<TheTypeYouWantToInstantiate>(paramTypes, paramValues);

// ...

public static T Construct<T>(Type[] paramTypes, object[] paramValues)
{
    Type t = typeof(T);

    ConstructorInfo ci = t.GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        null, paramTypes, null);

    return (T)ci.Invoke(paramValues);
}

Altri suggerimenti

È possibile utilizzare uno dei sovraccarichi di Activator.CreateInstance per fare questo: Activator.CreateInstance(Type type, bool nonPublic)

Usa true per l'argomento nonPublic. Perché true corrisponde a un costruttore predefinito pubblico o non pubblico; e false corrisponde solo un costruttore di default pubblico.

Ad esempio:

    class Program
    {
        public static void Main(string[] args)
        {
            Type type=typeof(Foo);
            Foo f=(Foo)Activator.CreateInstance(type,true);
        }       
    }

    class Foo
    {
        private Foo()
        {
        }
    }

E 'questa la domanda che erano dopo? Activator.CreateInstance con privata classe chiusa

Se la classe non è uno dei tuoi, allora suona come l'API è stato volutamente scritto per evitare questo, il che significa che è possibile il tuo approccio non è quello che gli scrittori API destinati. Date un'occhiata ai documenti e vedere se c'è un approccio consigliato di utilizzare questa classe.

Se do hanno il controllo sulla classe e vogliono implementare questo modello, quindi è in genere implementata tramite un metodo statico su una classe. Questo è un concetto chiave che rende il pattern Singleton, anche.

Ad esempio:

public PrivateCtorClass
{
    private PrivateCtorClass()
    {
    }

    public static PrivateCtorClass Create()
    {
        return new PrivateCtorClass();
    }
}

public SomeOtherClass
{
    public void SomeMethod()
    {
        var privateCtorClass = PrivateCtorClass.Create();
    }
}

La roba SqlCommandParameter è un buon esempio. Si aspettano di creare parametri chiamando le cose in questo modo:

var command = IDbConnnection.CreateCommand(...);
command.Parameters.Add(command.CreateParameter(...));

Il mio esempio non è grande codice, perché non dimostra l'impostazione delle proprietà dei parametri di comando o riutilizzo dei parametri / comandi, ma si ottiene l'idea.

Sarà anche utile se il vostro Type è private o internal:

 public static object CreatePrivateClassInstance(string typeName, object[] parameters)
    {
        Type type = AppDomain.CurrentDomain.GetAssemblies().
                 SelectMany(assembly => assembly.GetTypes()).FirstOrDefault(t => t.Name == typeName);
        return type.GetConstructors()[0].Invoke(parameters);
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top