2013-08-27 2 views
1

У меня есть 100 классов, имеющих похожие методы подписи, только их внутреннее определение отличается. Я буду передавать одно из имени класса в качестве строки, и мне нужно создать объект этого типа и вызвать методы. Я знаю, что могу использовать «Activator.CreateInstance», но точно не знаю, как в этом случае. Например, допустим, что у меня есть классы с именем Calculator1 to Calculator100. Я не уверен, как отличать его во второй строке в зависимости от строки имени класса.Создать объект из имени класса в строке

ObjectHandle handle = Activator.CreateInstance("NameSpaceCalculator", "Calculator1"); 
    var Calculator = (Calculator1)handle.Unwrap(); 
+1

Используйте общий интерфейс. – SLaks

+0

Вы * не будете * бросать его. Если эти классы не имеют общего интерфейса, кастинг даже не имеет смысла. Что именно ты пытаешься сделать? – aquinas

+0

Вы не можете сделать этого, если не коснуться какой-то «динамической». Однако вы можете использовать 'Reflection' для доступа к членам созданного объекта, не отбрасывая его на нужный тип. –

ответ

1

Это работает для меня, но интерфейс будет лучше подходят для этого:

void Main() 
{ 
    var x = CreateClass("A"); 
    x.Unwrap(); 
} 

public BaseC CreateClass(string typeName) 
{ 
    var type = Type.GetType(string.Format("MyNamespace.{0}",typeName); 
    return (BaseC)Activator.CreateInstance(type); 
} 


public class A : BaseC 
{ 
    public override void Unwrap() 
    { 
     Console.WriteLine("A"); 
    } 
} 

public class B : BaseC 
{ 
    public override void Unwrap() 
    { 
     Console.WriteLine("B"); 
    } 
} 

public class BaseC 
{ 
    public virtual void Unwrap() 
    { 
     Console.WriteLine("BaseC"); 
    } 
} 


//// Here is the approach with an Interface (note that overrides and virtual declaration needed. 





void Main() 
    { 
     var x = CreateClass<IBase>("MyNamespace","A"); 
     x.Unwrap(); 
    } 

    public T CreateClass<T>(string classNamespace, string typeName) where T : class 
    { 
     var type = Type.GetType(string.Format("{0}.{1}",classNamespace, typeName)); 
     return (T)Activator.CreateInstance(type); 
    } 


    public class A : IBase 
    { 
     public void Unwrap() 
     { 
      Console.WriteLine("A"); 
     } 
    } 

    public class B : IBase 
    { 
     public void Unwrap() 
     { 
      Console.WriteLine("B"); 
     } 
    } 

    public interface IBase 
    { 
     void Unwrap(); 
    } 
+0

Я использовал подход CreateClass из Саддама. Он отлично работает, но в вашем Baseclass метод должен быть виртуальным, поэтому вызывается дочерний метод. – Dannydust

+0

Я также устанавливаю подход, используя интерфейс. Это намного лучше, потому что вам не нужны переопределения и виртуальные методы. – Dannydust

1

Вы можете либо использовать общий интерфейс с Unwrap() методом, определенным и актерский к этому интерфейсу, или вы могли бы использовать отражение, чтобы найти метод Unwrap и назвать его.

Если вы не загружаете сборку во время выполнения и не можете использовать в ней интерфейс с указанием времени компиляции, я бы использовал первый вариант, поскольку отражение в этом случае медленное и сложное.

+0

C# отражение на самом деле довольно быстро. –

+0

'UnWrap()' является частью 'ObjectHandle', а не его классами Calculator, я не уверен, почему в первой планете есть приведение к' ObjectHandle' –

+0

@ sa_ddam213 Теперь я вижу. Я все еще думаю, что писать общий интерфейс будет лучшим решением. – TheEvilPenguin

1

Perhap вы можете получить правильный тип сначала, чтобы создать экземпляр.

public CalculatorBase CreateClass(string typeName) 
{ 
    var type = Type.GetType(string.Format("NameSpaceCalculator.{0}",typeName)); 
    return (CalculatorBase)Activator.CreateInstance(type); 
} 
+0

Я пробовал это, но он вызывает методы класса CalculatorBase вместо этого конкретного класса. – Multicaster