Birisi Activator.CreateInstance()
amacı ayrıntılı olarak açıklayabilir mi?
c#.net
, bunu yapmanın yolu budur Object xyz = Class.forName(className).newInstance();
.
Birisi Activator.CreateInstance()
amacı ayrıntılı olarak açıklayabilir mi?
c#.net
, bunu yapmanın yolu budur Object xyz = Class.forName(className).newInstance();
.
Yanıtlar:
MyFancyObject
Aşağıdaki gibi bir sınıfınız olduğunu varsayalım :
class MyFancyObject
{
public int A { get;set;}
}
Dönmenizi sağlar:
String ClassName = "MyFancyObject";
içine
MyFancyObject obj;
kullanma
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
ve daha sonra aşağıdaki gibi şeyler yapabilir:
obj.A = 100;
Amacı bu. Type
Bir dizede sınıf adı yerine a sağlamak gibi birçok başka aşırı yüklemeye de sahiptir . Neden böyle bir problemin olsun farklı bir hikaye. İşte buna ihtiyacı olan bazı insanlar:
String ClassName = "My.Namespace.MyFancyObject";
) dahil ettiğimden emin olmalıydım .
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
ama türle döküm yapmak yerine. ClassName'den yapılan türle döküm? Bunun gibi Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
mi?
Size neden böyle bir şey kullanmanız gerektiğine dair bir örnek verebilirim. Seviyenizi ve düşmanlarınızı bir XML dosyasında saklamak istediğiniz bir oyun düşünün. Bu dosyayı ayrıştırdığınızda, bunun gibi bir öğeye sahip olabilirsiniz.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
şimdi yapabileceğiniz şey, seviye dosyanızda bulunan nesneleri dinamik olarak oluşturmaktır.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Bu, dinamik ortamlar oluşturmak için çok kullanışlıdır. Elbette bunu Eklenti veya eklenti senaryoları ve daha fazlası için kullanmak da mümkündür.
İyi arkadaşım MSDN bunu size bir örnekle açıklayabilir
Gelecekte bağlantının veya içeriğin değişmesi durumunda kullanılacak kod:
using System;
class DynamicInstanceList
{
private static string instanceSpec = "System.EventArgs;System.Random;" +
"System.Exception;System.Object;System.Version";
public static void Main()
{
string[] instances = instanceSpec.Split(';');
Array instlist = Array.CreateInstance(typeof(object), instances.Length);
object item;
for (int i = 0; i < instances.Length; i++)
{
// create the object from the specification string
Console.WriteLine("Creating instance of: {0}", instances[i]);
item = Activator.CreateInstance(Type.GetType(instances[i]));
instlist.SetValue(item, i);
}
Console.WriteLine("\nObjects and their default values:\n");
foreach (object o in instlist)
{
Console.WriteLine("Type: {0}\nValue: {1}\nHashCode: {2}\n",
o.GetType().FullName, o.ToString(), o.GetHashCode());
}
}
}
// This program will display output similar to the following:
//
// Creating instance of: System.EventArgs
// Creating instance of: System.Random
// Creating instance of: System.Exception
// Creating instance of: System.Object
// Creating instance of: System.Version
//
// Objects and their default values:
//
// Type: System.EventArgs
// Value: System.EventArgs
// HashCode: 46104728
//
// Type: System.Random
// Value: System.Random
// HashCode: 12289376
//
// Type: System.Exception
// Value: System.Exception: Exception of type 'System.Exception' was thrown.
// HashCode: 55530882
//
// Type: System.Object
// Value: System.Object
// HashCode: 30015890
//
// Type: System.Version
// Value: 0.0
// HashCode: 1048575
Bunu da yapabilirsiniz -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
Tam olarak neyin işe yaradığı ve bunun diğer çözümlerle nasıl bir ilişkisi olduğu konusunda ek açıklama yapabilir misiniz ?
CreateInstance
döndüğü yerin farklı bir aşırı yüklemesinde System.Runtime.Remoting.ObjectHandle
.
Bundan sonra iyi bir örnek olabilir: örneğin, bir dizi Kaydediciniz var ve kullanıcının, yapılandırma dosyası aracılığıyla çalışma zamanında kullanılacak türü belirlemesine izin veriyorsunuz.
Sonra:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
VEYA başka bir durum, varlık oluşturan ve aynı zamanda DB'den alınan verilerle bir varlığın başlatılmasından sorumlu olan bir ortak varlık fabrikasına sahip olduğunuzdur:
(Yalancı kod)
public TEntity CreateEntityFromDataRow<TEntity>(DataRow row)
where TEntity : IDbEntity, class
{
MethodInfo methodInfo = typeof(T).GetMethod("BuildFromDataRow");
TEntity instance = Activator.CreateInstance(typeof(TEntity)) as TEntity;
return methodInfo.Invoke(instance, new object[] { row } ) as TEntity;
}
typeof(loggerType)
sonuçloggerType is a variable and used like a type
Activator.CreateInstance
Yöntem belirlenen parametreleri en iyi eşleştiğini yapıcısı kullanarak belirtilen türde bir örneğini oluşturur.
Örneğin, tür adını bir dizge olarak aldığınızı ve dizeyi bu türden bir örnek oluşturmak için kullanmak istediğinizi varsayalım. Bunun için kullanabilirsiniz Activator.CreateInstance
:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
İşte uygulamasını daha ayrıntılı olarak açıklayan bir MSDN makalesi:
new Foo()
. Bence OP daha gerçekçi bir örnek istedi.
CreateInstance
, tasarım zamanında başlatacağınız nesnenin türünü bilmiyorsanız. Bu örnekte, tür Foo
olarak yayınladığınız için bunun bir tür olduğunu açıkça biliyorsunuz Foo
. Bunu asla yapmazsın çünkü yapabilirsin Foo foo = new Foo()
.
Deepee1 kapalı Bina ve bu , burada bir dizede bir sınıf adı kabul edin ve sonra da LINQ ile bir veritabanına okuma ve yazma için kullanmak nasıl. Deepee1'in dönüştürmesi yerine "dinamik" kullanıyorum çünkü özellikleri atamama izin veriyor, bu da bizim istediğimiz herhangi bir tabloyu dinamik olarak seçmemizi ve çalıştırmamızı sağlıyor.
Type tableType = Assembly.GetExecutingAssembly().GetType("NameSpace.TableName");
ITable itable = dbcontext.GetTable(tableType);
//prints contents of the table
foreach (object y in itable) {
string value = (string)y.GetType().GetProperty("ColumnName").GetValue(y, null);
Console.WriteLine(value);
}
//inserting into a table
dynamic tableClass = Activator.CreateInstance(tableType);
//Alternative to using tableType, using Tony's tips
dynamic tableClass = Activator.CreateInstance(null, "NameSpace.TableName").Unwrap();
tableClass.Word = userParameter;
itable.InsertOnSubmit(tableClass);
dbcontext.SubmitChanges();
//sql equivalent
dbcontext.ExecuteCommand("INSERT INTO [TableNme]([ColumnName]) VALUES ({0})", userParameter);
Sınıfı zaten biliyorsan ve onu oyuncu kadrosuna alacak olsaydın neden kullanasın ki? Neden bunu eski moda bir şekilde yapıp, sınıfı her zaman başarabildiğiniz gibi yapmıyorsunuz? Normal şekilde yapılmasına göre bunun hiçbir avantajı yok. Metni alıp bu şekilde işlemenin bir yolu var mı:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Pizza olduğunu zaten biliyorsam, bunun bir avantajı yok:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
ancak eğer varsa Magic yönteminin büyük bir avantaj olduğunu görüyorum.
Yansıma ile birleştiğinde, Activator.CreateInstance'in , aşağıdaki yanıtta açıklandığı gibi, saklı yordam sonucunu özel bir sınıfa eşleştirmede çok yardımcı olduğunu buldum .
CreateInstance(Type type)
eşleşmesini tavsiye ederimCreateInstance<T>()
.