Kap egy új objektum például egy Type

szavazat
554

Egy nem mindig tudja a típus egy objektum fordításkor, de létre kell hoznia egy példányt a típus. Hogyan kap egy új objektum például egy típus?

A kérdést 03/08/2008 17:29
a forrás felhasználó
Más nyelveken...                            


12 válasz

szavazat
35

Egy végrehajtását ez a probléma az, hogy megpróbáljuk felhívni a paraméter nélküli konstruktor típusa:

public static object GetNewObject(Type t)
{
    try
    {
        return t.GetConstructor(new Type[] { }).Invoke(new object[] { });
    }
    catch
    {
        return null;
    }
}

Itt ugyanazt a megközelítést tartalmazott egy általános módszer:

public static T GetNewObject<T>()
{
    try
    {
        return (T)typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { });
    }
    catch
    {
        return default(T);
    }
}
Válaszolt 03/08/2008 17:31
a forrás felhasználó

szavazat
709

Az Activatorosztály a gyökér Systemnévtér elég erős.

Van egy csomó túlterhelés tompított paraméterek a kivitelező és az ilyen. Nézze meg a dokumentációt:

http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx

vagy (új út)

https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance

Íme néhány egyszerű példa:

ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);

ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
Válaszolt 03/08/2008 17:35
a forrás felhasználó

szavazat
11

Ha ez valami, ami nevezhető tétel kérelem esetben ez sokkal gyorsabb összeállítására és gyorsítótár dinamikus kód használata helyett aktivátor vagy ConstructorInfo.Invoke(). Két egyszerű lehetőség dinamikus fordítás összeállítani Linq kifejezések vagy néhány egyszerű ILműveleti kódok ésDynamicMethod . Akárhogy is, a különbség óriási, amikor elkezd bekerülni szűk hurkok vagy több hívás.

Válaszolt 25/08/2008 14:31
a forrás felhasználó

szavazat
113
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);

Az Activatorosztály egy általános változata, ami ezt egy kicsit könnyebb:

ObjectType instance = Activator.CreateInstance<ObjectType>();
Válaszolt 25/08/2008 14:33
a forrás felhasználó

szavazat
7

Nem lenne az általános T t = new T();munka?

Válaszolt 17/08/2010 15:30
a forrás felhasználó

szavazat
3
public AbstractType New
{
    get
    {
        return (AbstractType) Activator.CreateInstance(GetType());
    }
}
Válaszolt 10/09/2012 00:08
a forrás felhasználó

szavazat
7

Ha szeretné használni az alapértelmezett konstruktor majd az oldatot használva System.Activatora korábban bemutatott talán a legkényelmesebb. Azonban, ha a típus hiányzik az alapértelmezett konstruktor vagy meg kell használni egy nem alapértelmezett, akkor egy lehetőség, hogy reflexió vagy System.ComponentModel.TypeDescriptor. Abban az esetben, mérlegelés, elég tudni, a típus neve (annak névtér).

Példa a reflexió:

ObjectType instance = 
    (ObjectType)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(
        typeName: objectType.FulName, // string including namespace of the type
        ignoreCase: false,
        bindingAttr: BindingFlags.Default,
        binder: null,  // use default binder
        args: new object[] { args, to, constructor },
        culture: null, // use CultureInfo from current thread
        activationAttributes: null
    );

Példa segítségével TypeDescriptor:

ObjectType instance = 
    (ObjectType)System.ComponentModel.TypeDescriptor.CreateInstance(
        provider: null, // use standard type description provider, which uses reflection
        objectType: objectType,
        argTypes: new Type[] { types, of, args },
        args: new object[] { args, to, constructor }
    );
Válaszolt 22/07/2013 22:03
a forrás felhasználó

szavazat
9

A meglehetősen egyszerű. Tegyük fel, hogy a classname van Car, és a névtér Vehicles, majd át a paramétert Vehicles.Car, amely visszaállítja típusú objektum Car. Mint ez hozhat létre bármely példányának minden osztályban dinamikusan.

public object GetInstance(string strNamesapace)
{         
     Type t = Type.GetType(strNamesapace); 
     return  Activator.CreateInstance(t);         
}

Ha a teljes nevét (azaz Vehicles.Carebben az esetben) egy másik szerelvény, a Type.GetTypenull lesz. Ilyen esetekben van végigjárjuk minden szerelvényt, és megtalálja a Type. Az, hogy akkor az alábbi kódot

public object GetInstance(string strFullyQualifiedName)
{
     Type type = Type.GetType(strFullyQualifiedName);
     if (type != null)
         return Activator.CreateInstance(type);
     foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
     {
         type = asm.GetType(strFullyQualifiedName);
         if (type != null)
             return Activator.CreateInstance(type);
     }
     return null;
 }

És lehet kapni a példány hívja a fenti módszerrel.

object objClassInstance = GetInstance("Vehicles.Car");
Válaszolt 03/11/2014 06:11
a forrás felhasználó

szavazat
3

Azt is át ezt a kérdést, mert kerestem, egy egyszerű CloneObject eljárás tetszőleges osztály (az alapértelmezett konstruktor)

A generikus eljárás akkor szükséges, hogy a típust valósít New ().

Public Function CloneObject(Of T As New)(ByVal src As T) As T
    Dim result As T = Nothing
    Dim cloneable = TryCast(src, ICloneable)
    If cloneable IsNot Nothing Then
        result = cloneable.Clone()
    Else
        result = New T
        CopySimpleProperties(src, result, Nothing, "clone")
    End If
    Return result
End Function

A nem-generikus vállalja a típus egy alapértelmezett konstruktor és a fogást kivételt, ha nem.

Public Function CloneObject(ByVal src As Object) As Object
    Dim result As Object = Nothing
    Dim cloneable As ICloneable
    Try
        cloneable = TryCast(src, ICloneable)
        If cloneable IsNot Nothing Then
            result = cloneable.Clone()
        Else
            result = Activator.CreateInstance(src.GetType())
            CopySimpleProperties(src, result, Nothing, "clone")
        End If
    Catch ex As Exception
        Trace.WriteLine("!!! CloneObject(): " & ex.Message)
    End Try
    Return result
End Function
Válaszolt 24/03/2015 18:10
a forrás felhasználó

szavazat
78

Összeállította kifejezés legjobb módja! (A teljesítmény többször létre például futási idő).

static readonly Func<X> YCreator = Expression.Lambda<Func<X>>(
   Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
 ).Compile();

X x = YCreator();

Statisztika (2012):

    Iterations: 5000000
    00:00:00.8481762, Activator.CreateInstance(string, string)
    00:00:00.8416930, Activator.CreateInstance(type)
    00:00:06.6236752, ConstructorInfo.Invoke
    00:00:00.1776255, Compiled expression
    00:00:00.0462197, new

Statisztika (2015, a .NET 4.5, x64):

    Iterations: 5000000
    00:00:00.2659981, Activator.CreateInstance(string, string)
    00:00:00.2603770, Activator.CreateInstance(type)
    00:00:00.7478936, ConstructorInfo.Invoke
    00:00:00.0700757, Compiled expression
    00:00:00.0286710, new

Statisztika (2015, a .NET 4.5, x86):

    Iterations: 5000000
    00:00:00.3541501, Activator.CreateInstance(string, string)
    00:00:00.3686861, Activator.CreateInstance(type)
    00:00:00.9492354, ConstructorInfo.Invoke
    00:00:00.0719072, Compiled expression
    00:00:00.0229387, new

Statisztika (2017 LINQPad 5.22.02 / x64 / .NET 4.6):

    Iterations: 5000000
    No args
    00:00:00.3897563, Activator.CreateInstance(string assemblyName, string typeName)
    00:00:00.3500748, Activator.CreateInstance(Type type)
    00:00:01.0100714, ConstructorInfo.Invoke
    00:00:00.1375767, Compiled expression
    00:00:00.1337920, Compiled expression (type)
    00:00:00.0593664, new
    Single arg
    00:00:03.9300630, Activator.CreateInstance(Type type)
    00:00:01.3881770, ConstructorInfo.Invoke
    00:00:00.1425534, Compiled expression
    00:00:00.0717409, new

Teljes kód:

static X CreateY_New()
{
    return new Y();
}

static X CreateY_New_Arg(int z)
{
    return new Y(z);
}

static X CreateY_CreateInstance()
{
    return (X)Activator.CreateInstance(typeof(Y));
}

static X CreateY_CreateInstance_String()
{
    return (X)Activator.CreateInstance("Program", "Y").Unwrap();
}

static X CreateY_CreateInstance_Arg(int z)
{
    return (X)Activator.CreateInstance(typeof(Y), new object[] { z, });
}

private static readonly System.Reflection.ConstructorInfo YConstructor =
    typeof(Y).GetConstructor(Type.EmptyTypes);
private static readonly object[] Empty = new object[] { };
static X CreateY_Invoke()
{
    return (X)YConstructor.Invoke(Empty);
}

private static readonly System.Reflection.ConstructorInfo YConstructor_Arg =
    typeof(Y).GetConstructor(new[] { typeof(int), });
static X CreateY_Invoke_Arg(int z)
{
    return (X)YConstructor_Arg.Invoke(new object[] { z, });
}

private static readonly Func<X> YCreator = Expression.Lambda<Func<X>>(
   Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();
static X CreateY_CompiledExpression()
{
    return YCreator();
}

private static readonly Func<X> YCreator_Type = Expression.Lambda<Func<X>>(
   Expression.New(typeof(Y))
).Compile();
static X CreateY_CompiledExpression_Type()
{
    return YCreator_Type();
}

private static readonly ParameterExpression YCreator_Arg_Param = Expression.Parameter(typeof(int), "z");
private static readonly Func<int, X> YCreator_Arg = Expression.Lambda<Func<int, X>>(
   Expression.New(typeof(Y).GetConstructor(new[] { typeof(int), }), new[] { YCreator_Arg_Param, }),
   YCreator_Arg_Param
).Compile();
static X CreateY_CompiledExpression_Arg(int z)
{
    return YCreator_Arg(z);
}

static void Main(string[] args)
{
    const int iterations = 5000000;

    Console.WriteLine("Iterations: {0}", iterations);

    Console.WriteLine("No args");
    foreach (var creatorInfo in new[]
    {
        new {Name = "Activator.CreateInstance(string assemblyName, string typeName)", Creator = (Func<X>)CreateY_CreateInstance},
        new {Name = "Activator.CreateInstance(Type type)", Creator = (Func<X>)CreateY_CreateInstance},
        new {Name = "ConstructorInfo.Invoke", Creator = (Func<X>)CreateY_Invoke},
        new {Name = "Compiled expression", Creator = (Func<X>)CreateY_CompiledExpression},
        new {Name = "Compiled expression (type)", Creator = (Func<X>)CreateY_CompiledExpression_Type},
        new {Name = "new", Creator = (Func<X>)CreateY_New},
    })
    {
        var creator = creatorInfo.Creator;

        var sum = 0;
        for (var i = 0; i < 1000; i++)
            sum += creator().Z;

        var stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < iterations; ++i)
        {
            var x = creator();
            sum += x.Z;
        }
        stopwatch.Stop();
        Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name);
    }

    Console.WriteLine("Single arg");
    foreach (var creatorInfo in new[]
    {
        new {Name = "Activator.CreateInstance(Type type)", Creator = (Func<int, X>)CreateY_CreateInstance_Arg},
        new {Name = "ConstructorInfo.Invoke", Creator = (Func<int, X>)CreateY_Invoke_Arg},
        new {Name = "Compiled expression", Creator = (Func<int, X>)CreateY_CompiledExpression_Arg},
        new {Name = "new", Creator = (Func<int, X>)CreateY_New_Arg},
    })
    {
        var creator = creatorInfo.Creator;

        var sum = 0;
        for (var i = 0; i < 1000; i++)
            sum += creator(i).Z;

        var stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < iterations; ++i)
        {
            var x = creator(i);
            sum += x.Z;
        }
        stopwatch.Stop();
        Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name);
    }
}

public class X
{
  public X() { }
  public X(int z) { this.Z = z; }
  public int Z;
}

public class Y : X
{
    public Y() {}
    public Y(int z) : base(z) {}
}
Válaszolt 30/04/2015 16:13
a forrás felhasználó

szavazat
8

Használata nélkül Reflection:

private T Create<T>() where T : class, new()
{
    return new T();
}
Válaszolt 30/06/2015 12:51
a forrás felhasználó

szavazat
5

Mivel ez a probléma az aktivátor fog működni, ha van egy paraméter ctor. Ha ez a megszorítás megfontolni

System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject()
Válaszolt 30/06/2015 16:35
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more