2015-03-10 4 views
0

Итак, у меня есть базовый набор абстрактных классов с использованием пространства имен BaseEngine, и настоящий игровой проект, получающий набор.В C#, как у вас есть глобальный универсальный класс?

Есть много базовых классов, которые имеют набор абстрактных методов и предопределенных методов, таких как: Предмет, сущность, мастерство

public abstract class Item 
{ 
    public string name; 
    public void DestroyItemInBaseEngine() 
    { 
     // bunch of codes 
    } 
    public abstract void BakeItemTheWayYouWant(); 
} 

public abstract class SkillManager 
{ 
    public abstract T InteractItemWithSkill<T> (T item) 
     where T:Item, new(); //not sure if this particular line is valid, but this was written just to help you understand 
} 

И происходящие классы, такие как:

public class GameItem : Item 
{ 
    public int variableSpecificToThisGameProject; 

    // and other implementation for this specific game... 
} 

Теперь, В BaseEngine у ​​него были бы абстрактные классы, которые ссылаются на Item несколько раз на таких менеджеров, как BaseItemManager. Каждая игра управлялась бы по-разному, чтобы эти менеджеры также были получены. Когда конкретный игровой проект получает BaseItemManager, ему придется использовать GameItem.

BaseEngine был создан для использования с различными проектами, в основном набором абстрактных классов.

Каждый раз, когда эти производные объекты именуются в проекте игры, вы должны либо бросить его, или использовать общий тип в абстрактных методов, таких как, например:

if (ValidateItemObject<GameItem> (GameItem item) != null) 
    // do something with it 

Итак, потому что GameItem и другие типы решили во время компиляции все равно нужно объявить что-то вроде T = GameItem, S = GameSkill для всего проекта, поэтому нам не нужно упоминать каждый раз, когда вызываются связанные методы (например, выше) или классы?

Я попытался изо всех сил сделать мое дело максимально ясным, но дайте мне знать, если не ясно, что я пытаюсь сделать.

EDIT:

protected abstract T ConvertTableToItem<T> (T item, LuaTable luaTable) where T:BaseItem; 


protected override ProjectItem SetItemAPI<ProjectItem> (ProjectItem newItem, LuaTable luaTable) 
{ 
    newItem.desc = "test"; 
} 

Это не будет работать говоря убывание не является членом класса. Я могу гарантировать, что это так. desc (public string desc) определяется в ProjectItem.

ProjectItem - производный класс BaseItem.

+0

Итак, вы устали от того, что у вас есть 'ValidateItemObject (item)' и скорее всего хотите получить псевдоним проекта, такой как 'ValidateGameItem (item)'? Btw Я думаю 'if (ValidateItemObject (элемент GameItem)! = Null)' недопустимый синтаксис. – bokibeg

+0

Да! Например, глобальный тип псевдонима, так сказать. Причина не в том, что я просто устал, но некоторым BaseEngineManager придется ссылаться на объекты, подобные GameItem, и управлять ими. Например, BaseItemManager имеет словарь (где T будет GameItem), а BaseSkillManager будет пытаться использовать что-то вроде «BaseItemManager .dictionary.ContainsKey (itemID)», но на момент написания базового кода, поскольку BaseEngine предназначенный для будущих проектов, мы не знаем, что GameItem существует. –

ответ

2

Если вы хотите объявить класс с параметром фиксированного типа для общего типа, проще всего просто наследовать общий тип, указав требуемый параметр типа. Например:

static class SomeSpecificClass : SomeBaseClass<GameItem> { ... } 

Тогда любой способ, в SomeBaseClass<T>, что зависит от типа параметра T можно назвать с помощью SomeSpecificClass без указания параметра типа T.

Это означает, что другой инструмент в вашем ящике инструментов, который, вероятно, адресовал хотя бы пример, который вы предоставили, - это использовать вывод типа C# для общих методов.

Например, если у вас есть базовый класс шаблонный метод так:

class SomeBaseClass 
{ 
    public static T ValidateItemObject<T>(T item) where T : Item 
    { 
     // ...something 
    } 
} 

Тогда вы на самом деле не нужно использовать параметр типа при вызове метода, если в качестве параметра вы передадите правильно напечатан.Например:

GameItem gameItem = ...; 

if (SomeBaseClass.ValidateItemObject(gameItem) != null) 
{ 
    // ...something 
} 

(Естественно, если код находится в классе, который наследует SomeBaseClass, то вы на самом деле не нужно указать имя класса при вызове метода).

К сожалению, ваш фактический пример кода довольно расплывчатый. Но, основываясь на комментарии к вопросу и вашему ответу, кажется, что вышеизложенное должно ответить на ваш вопрос. Если нет, подумайте об изменении вашего вопроса, чтобы предоставить a more specific, complete, but minimal code example, а также четкое описание того, что сейчас делает этот пример, и как вы хотите его изменить. Вы также можете прочитать https://stackoverflow.com/help/how-to-ask советы по улучшению ясности вопроса.

+0

Извините, что я не был достаточно ясен. Я отредактировал и добавил что-то из своего кода. абстрактный определяется в базовом менеджере, а метод переопределения определяется в производном менеджере. Не могли бы вы посмотреть мой добавленный код и посмотреть, почему он не работает? –

+1

@MaxHunter: похоже, вы пытаетесь объявить общий метод с определенным типом. Но это не разрешено, и на самом деле C# обрабатывает ваше объявление, как любое другое объявление универсального метода. Он интерпретирует «ProjectItem» в этом контексте как параметр родового типа, и без каких-либо ограничений тип не будет иметь нужного члена. Попробуйте 'T SetItemAPI (T newItem, LuaTable luaTable), где T: ProjectItem'. Я не могу _guarantee_, который будет работать, поскольку вы все еще не предоставляете полный пример кода. Но это должно быть по крайней мере ближе к тому, что вы хотите. –

+0

К сожалению, это невозможно. Поскольку ProjectItem может быть чем угодно в будущих проектах. Я думаю, это просто невозможно с C# в том, что я пытаюсь сделать ... –

Смежные вопросы