Alguém pode explicar o Activator.CreateInstance()
objetivo em detalhes?
c#.net
maneira de fazer Object xyz = Class.forName(className).newInstance();
.
Alguém pode explicar o Activator.CreateInstance()
objetivo em detalhes?
c#.net
maneira de fazer Object xyz = Class.forName(className).newInstance();
.
Respostas:
Digamos que você tenha uma classe chamada MyFancyObject
como esta abaixo:
class MyFancyObject
{
public int A { get;set;}
}
Permite ativar:
String ClassName = "MyFancyObject";
Para dentro
MyFancyObject obj;
Usando
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
e pode fazer coisas como:
obj.A = 100;
Esse é o seu propósito. Ele também possui muitas outras sobrecargas, como fornecer um Type
nome em vez do nome da classe em uma sequência. Por que você teria um problema como esse é uma história diferente. Aqui estão algumas pessoas que precisavam:
String ClassName = "My.Namespace.MyFancyObject";
).
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
mas em vez de transmitir com o tipo Transmitir com o tipo criado a partir do ClassName? Gosta disso Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Bem, eu posso te dar um exemplo de por que usar algo assim. Pense em um jogo em que você deseja armazenar seu nível e inimigos em um arquivo XML. Ao analisar este arquivo, você pode ter um elemento como este.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
o que você pode fazer agora é criar dinamicamente os objetos encontrados no seu arquivo de nível.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Isso é muito útil para criar ambientes dinâmicos. É claro que também é possível usar isso para cenários de plug-in ou add-in e muito mais.
Meu bom amigo MSDN pode explicar isso para você, com um exemplo
Aqui está o código, caso o link ou o conteúdo seja alterado no futuro:
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
Você também pode fazer isso -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
é preciso e como isso se relaciona com outras soluções?
CreateInstance
onde ele retorna System.Runtime.Remoting.ObjectHandle
.
Um bom exemplo pode ser o próximo: por exemplo, você tem um conjunto de Registradores e permite que o usuário especifique o tipo a ser usado no tempo de execução via arquivo de configuração.
Então:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
OU outro caso é quando você tem uma fábrica de entidades comum, que cria uma entidade, e também é responsável na inicialização de uma entidade pelos dados recebidos do DB:
(pseudo-código)
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)
resulta emloggerType is a variable and used like a type
O Activator.CreateInstance
método cria uma instância de um tipo especificado usando o construtor que melhor corresponde aos parâmetros especificados.
Por exemplo, digamos que você tenha o nome do tipo como uma sequência e deseja usá-la para criar uma instância desse tipo. Você pode usar Activator.CreateInstance
para isso:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Aqui está um artigo do MSDN que explica sua aplicação com mais detalhes:
new Foo()
. Eu acho que o OP queria um exemplo mais realista.
CreateInstance
é se você não souber o tipo de objeto que você irá instanciar no momento do design. Neste exemplo, você sabe claramente que é do tipo, Foo
uma vez que o está convertendo como tipo Foo
. Você nunca faria isso porque pode simplesmente fazer Foo foo = new Foo()
.
Com base no deepee1 e isso , veja como aceitar um nome de classe em uma string e, em seguida, usá-lo para ler e gravar em um banco de dados com LINQ. Eu uso "dinâmico" em vez da conversão do deepee1 porque ele me permite atribuir propriedades, o que nos permite selecionar e operar dinamicamente em qualquer tabela que desejar.
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);
Por que você o usaria se você já conhecesse a classe e a apresentasse? Por que não fazer da maneira antiga e fazer da classe como você sempre faz? Não há vantagem nisso sobre o modo como é feito normalmente. Existe uma maneira de pegar o texto e operá-lo assim:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Se eu já sei que é uma Pizza, não há vantagem em:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
mas vejo uma enorme vantagem no método Magic, se existir.
Juntamente com a reflexão, achei o Activator.CreateInstance muito útil no mapeamento do resultado do procedimento armazenado para uma classe personalizada, conforme descrito na resposta a seguir .
CreateInstance(Type type)
seja combinada com aCreateInstance<T>()
sobrecarga.