Класс Activator
в корневом пространстве имен System
довольно мощный.
Существует много перегрузок для передачи параметров конструктору и тому подобное. Посмотрите документацию по адресу:
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
blockquote>или (новый путь)
https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance
blockquote>Вот несколько простых примеров:
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType); ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
Если вы хотите использовать конструктор по умолчанию, то решение с использованием System.Activator
, представленное ранее, возможно, наиболее удобно. Однако, если в типе отсутствует конструктор по умолчанию или вам нужно использовать нестандартный, тогда опция должна использовать отражение или System.ComponentModel.TypeDescriptor
. В случае отражения достаточно знать только имя типа (с его пространством имен).
Пример с использованием отражения:
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
);
Пример с помощью 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 }
);
Я могу решить этот вопрос, потому что я пытался реализовать простой метод CloneObject для произвольного класса (с конструктором по умолчанию)
С помощью общего метода вы можете потребовать, чтобы тип реализовал 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
С не-generic предположим, что тип имеет конструктор по умолчанию и исключает исключение, если это не так.
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
Если это для чего-то, что будет много называться в экземпляре приложения, намного быстрее выполнить компиляцию и кеширование динамического кода вместо использования активатора или ConstructorInfo.Invoke()
. Две простые опции для динамической компиляции компилируются Linq Expressions или некоторые простые IL
опкоды и DynamicMethod
. В любом случае разница будет огромной, когда вы начнете получать плотные петли или несколько вызовов.
Это довольно просто. Предположим, что ваше имя класса Car
, а пространство имен - Vehicles
, затем передайте параметр как Vehicles.Car
, который возвращает объект типа Car
. Подобным образом вы можете создать любой экземпляр любого класса динамически.
public object GetInstance(string strNamesapace)
{
Type t = Type.GetType(strNamesapace);
return Activator.CreateInstance(t);
}
Если ваше Полноценное имя (т. Е. Vehicles.Car
в этом случае) находится в другой сборке, Type.GetType
будет null. В таких случаях вы прокручиваете все сборки и находите Type
. Для этого вы можете использовать приведенный ниже код
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;
}
. Вы можете получить экземпляр, вызвав вышеуказанный метод.
object objClassInstance = GetInstance("Vehicles.Car");
public AbstractType New
{
get
{
return (AbstractType) Activator.CreateInstance(GetType());
}
}
Учитывая эту проблему, активатор будет работать, когда есть без параметров ctor. Если это ограничение, рассмотрим использование
System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject()