Bir Tür yeni bir nesne örneği alın

oy
554

Bir her zaman derleme zamanında bir nesnenin türü bilmiyor olabilir, ama Tipi örneğini oluşturmak gerekebilir. Nasıl bir Tip yeni bir nesne örneği alabilirim?

Oluştur 03/08/2008 saat 17:29
kaynak kullanıcı
Diğer dillerde...                            


12 cevaplar

oy
709

ActivatorKök içindeki sınıf Systemad oldukça güçlüdür.

yapıcı ve bu tür parametreleri geçmek için aşırı bir yeri vardır. belgeleri de göz atın:

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

ya da (yeni bir yol)

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

İşte bazı basit örnekler verilmiştir:

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

ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
Cevap 03/08/2008 saat 17:35
kaynak kullanıcı

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

ActivatorSınıf bu biraz daha kolay hale getiren bir jenerik varyantı vardır:

ObjectType instance = Activator.CreateInstance<ObjectType>();
Cevap 25/08/2008 saat 14:33
kaynak kullanıcı

oy
78

Derleyen ifadesi en iyi yoldur! (Performansı için sürekli çalışma zamanında bir örneğini oluşturmak için).

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

X x = YCreator();

İstatistikler (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

İstatistikler (2015, .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

İstatistikler (2015, .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

İstatistikler (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

Tam kod:

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) {}
}
Cevap 30/04/2015 saat 16:13
kaynak kullanıcı

oy
35

Bu sorunun bir uygulama Türü parametresi olmayan kurucusunu çağırmak için çalışmaktır:

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

İşte jenerik yöntemle bulunan aynı yaklaşım geçerli:

public static T GetNewObject<T>()
{
    try
    {
        return (T)typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { });
    }
    catch
    {
        return default(T);
    }
}
Cevap 03/08/2008 saat 17:31
kaynak kullanıcı

oy
11

Bu uygulama örneğinde çok çağrılacak şey ise, aktivatör kullanılarak veya yerine önbellek dinamik kod derlemek ve bir çok hızlıdır ConstructorInfo.Invoke(). Dinamik derleme için iki kolay seçenekler derlenmektedir Linq ifadeler ya da bazı basit ILişlem kodları veDynamicMethod . Eğer sıkı döngüler veya birden aramaların biniyorlar başladığınızda iki durumda da, fark çok büyük.

Cevap 25/08/2008 saat 14:31
kaynak kullanıcı

oy
9

Onun oldukça basit. Senin sınıfadı olduğunu varsayın Carve ad olduğu Vehicles, sonra da parametre geçirmek Vehicles.Cartüründeki nesne döndürür Car. Bunun gibi dinamik herhangi sınıfın herhangi örneğini oluşturabilirsiniz.

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

Senin Eğer Tamamen Nitelikli İsim (yani Vehicles.Carbu durumda) Başka bir montaj olduğunu Type.GetTypeboş olacaktır. Bu gibi durumlarda, tüm meclisleri aracılığıyla döngü var ve bulmak Type. Bunun için aşağıdaki kodu kullanabilirsiniz

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

Ve yukarıdaki yöntemini çağırarak örneğini alabilirsiniz.

object objClassInstance = GetInstance("Vehicles.Car");
Cevap 03/11/2014 saat 06:11
kaynak kullanıcı

oy
8

Yansıma kullanımı olmadan:

private T Create<T>() where T : class, new()
{
    return new T();
}
Cevap 30/06/2015 saat 12:51
kaynak kullanıcı

oy
7

Eğer varsayılan kurucu kullanmak istiyorsanız o zaman kullanarak çözüm System.Activatordaha önce sunulan muhtemelen en uygundur. Tipi bir varsayılan kurucu yoksun veya varsayılan olmayan bir birini kullanmak zorunda Ancak, daha sonra bir seçenek yansıması veya kullanmaktır System.ComponentModel.TypeDescriptor. Yansıma durumunda, (onun ad ile) sadece tip adını öğrenmek için yeterlidir.

Yansıma kullanarak Örnek:

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

Kullanılarak Örnek 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 }
    );
Cevap 22/07/2013 saat 22:03
kaynak kullanıcı

oy
7

Jenerik olmaz mıydı T t = new T();iş?

Cevap 17/08/2010 saat 15:30
kaynak kullanıcı

oy
5

parametresiz ctor olduğunda Aktivatör çalışacaktır bu sorunu göz önüne alındığında. Bu ise bir kısıtlama kullanmayı düşünün

System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject()
Cevap 30/06/2015 saat 16:35
kaynak kullanıcı

oy
3

Bu soru karşısında ben (varsayılan kurucu ile) keyfi sınıf için basit bir CloneObject yöntemini uygulamak için bakıyordu çünkü

Jenerik yöntemle Tür Yeni uygulayan () gerektirebilir.

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

genel olmayan tip bir varsayılan kurucu olduğunu varsayalım ve bunları yapmazsa bir istisna yakalamak.

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
Cevap 24/03/2015 saat 18:10
kaynak kullanıcı

oy
3
public AbstractType New
{
    get
    {
        return (AbstractType) Activator.CreateInstance(GetType());
    }
}
Cevap 10/09/2012 saat 00:08
kaynak kullanıcı

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