2008-11-02 3 views
0

Я пытаюсь создать функцию в C#, которая позволит мне при вызове вернуть ссылку на данный тип класса. Единственные типы таких функций, которые я видел, находятся в UnrealScript, и даже тогда функциональность жестко закодирована в его компилятор. Мне интересно, могу ли я сделать это на C#. Вот что я имею в виду (фрагмент кода из исходного кода UnrealScript):Ограничение класса и архетипы

native(278) final function actor Spawn 
(
    class<actor>  SpawnClass, 
    optional actor SpawnOwner, 
    optional name  SpawnTag, 
    optional vector SpawnLocation, 
    optional rotator SpawnRotation 
); 

Теперь в UScript вы могли бы назвать это так ...

local ActorChild myChildRef; //Ref to ActorChild which Extends 'actor' 
myChildRef = Spawn(class'ActorChild' ...); //rest of parameters taken out 
myChildRef.ChildMethod(); //method call to method existing inside class 'ActorChild' 

Который будет возвращать ссылку на объект класса «ActorChild 'и установите для него значение переменной myChildRef. Мне нужно сделать что-то подобное в C#.

Я искал Generics, но кажется, что для их использования мне нужно создать instace класса, где находится моя функция, и передать ему «общий» параметр. Это не очень желательно, так как мне не нужно будет использовать функцию «Spawn» для определенных классов, но мне все равно придется добавлять общий параметр к классу всякий раз, когда я его использую.

Я предполагаю, что будет упрощенный вопрос, как я могу вернуть тип, который я не знаю во время компиляции, и когда разные классы могут быть слишком много, чтобы ловушки.

Псевдо-код (прилипание к именам UScript класса, то есть актер):

//Function Sig 
public class<Actor> Create(class<Actor> CreatedClass) 
{ 
    return new CreatedClass; 
} 

//Function call 
ActorChild myChild = Create(class'ActorChild'); 

Любые идеи?

EDIT: Я хотел бы избежать явных приемов типов, которые возникли бы из вызова класса Created. Если я могу привести к желаемому объекту в методе «Создать» и вернуть «неизвестный тип», что бы это ни было, я был бы очень счастлив.

EDIT 2: Спасибо за ваши ответы.

ответ

2

Вместо того, чтобы использовать общий класс, использовать общий метод:

public T Spawn<T>() where T : new() 
{ 
    return new T(); 
} 

Сказав это, я предполагаю, что вы хотите чтобы сделать больше, чем просто слепо создать экземпляр, иначе вы могли бы просто позвонить new MyClass() себе.

1

Вы можете использовать класс System.Type для представления классов. Для получения ссылки на объекты типа, вы либо использовать TypeOf (в объеме, где класс фактически определяется)

System.Type t = typeof(ActorChild); 

или функция Type.GetType (если вы знаете только имя типа)

System.Type t = Type.GetType("NamespaceFoo.ActorChild"); 

вы можете использовать Reflection API для создания экземпляра

public object Create(System.Type ClassToCreate) 
{ 
    return ClassToCreate.GetConstructor(Type.EmptyTypes).Invoke(null); 
} 
+0

не страдает ли проблема «Type.GetType только смотрит в mscorlib»? – Jimmy 2008-11-02 06:08:43

+0

Действительно ли это? Я понимаю, что если вы поместите имя сборки после имени типа, оно будет выглядеть и в других сборках. См. Документацию для AssemblyQualifiedName в MSDN. – 2008-11-02 07:21:57

0

то, что вы пытаетесь достичь можно сделать довольно легко с отражением и что-то под названием Dynamic Method Invocation.

В принципе, вы будете использовать объект Type, метод Activator.CreateInstance и некоторые другие классные классы, такие как MethodInfo и ParameterInfo.

Вот пример, чтобы вы начали:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 

namespace Reflection 
{ 
    class SomeClass 
    { 
     private string StringPrimer = "The parameter text is: "; 
     public SomeClass(string text) 
     { 
      Console.WriteLine(StringPrimer + text); 
     } 
     public string getPrimer() //supplies the Primer in upper case, just for kicks 
     { 
      return StringPrimer.ToUpper(); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      SomeClass s = new SomeClass("this is an example of the classes normal hard-coded function.\nNow try feeding in some text"); 
      string t = Console.ReadLine(); 

      Console.WriteLine("Now feed in the class name (SomeClass in this case)"); 
      Type myType = Type.GetType("Reflection."+Console.ReadLine()); //Stores info about the class. 
      object myClass = Activator.CreateInstance(myType, new object[] { t }); //This dynamically calls SomeClass and sends in the text you enter as a parameter 

      //Now lets get the string primer, using the getPrimer function, dynamically 
      string primer = (string)myType.InvokeMember("getPrimer", 
                 BindingFlags.InvokeMethod | BindingFlags.Default, 
                 null, 
                 myClass, 
                 null); //This method takes the name of the method, some Binding flags, 
                   //a binder object that I left null, 
                   //the object that the method will be called from (would have been null if the method was static) 
                   //and an object array of parameters, just like in the CreateInstance method. 
      Console.WriteLine(primer); 
     } 
    } 
} 
Смежные вопросы