2013-02-25 7 views
2

Я играю с созданием каких-то беглых API; своего рода DSL. Я постоянно сталкиваюсь с конкретной проблемой, и я не нашел пути вокруг нее, здесь или где-то еще, что касается конкретной проблемы, как я ее вижу. Кроме того, я видел, как многие люди задают много вариантов этой проблемы.Методы расширения для общих классов

Вот, очевидно надуманным, пример того, что я хочу сделать ...

Run<Car>.Off<Road>(); 
Run<Car>.Off<Cliff>(); 
Run<Person>.Off<Road>(); 

Person pete = new Person(); 
pete.Run().Off<Road>(); 
pete.Run().Off<Cliff>(); 

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

public class Run<TActor, TTarget> 
{ 
    public Run() { } 
    public Run(TActor actor) { } 
    public Run(TActor actor, TTarget target) { } 

    public TActor Actor { get; set; } 
    public TTarget Target { get; set; } 
} 

public static class Run<TActor> 
{ 
    public static Run<TActor, TTarget> Off<TTarget>() 
    { 
     return new Run<TActor, TTarget>(); 
    } 
} 

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

public static class RunExtensions 
{ 
    public static TRun Run<TRun>(this TRun run) where TRun : Run<TActor, TTarget> 
    { 
     // doesn't compile 
    } 

    public static Run<TActor, TTarget> Run<TActor>(this TActor actor) 
    { 
     // obviously this doesn't work either 
    } 
} 
+4

«не компилируется» менее полезна, чем фактическое сообщение об ошибке, предоставленной компилятором. –

+0

Очень верно. Извини за это. Ошибка - неизвестный параметр (в зависимости от того, что там не существует). –

ответ

3

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

public static class RunExtensions 
{ 
    public static TRun Run<TRun, TActor, TTarget>(this TRun map) 
     where TRun : Run<TActor, TTarget> 
    { 
     return map; 
    } 

    public static Run<TActor, TTarget> Run<TActor, TTarget>(this TActor actor) 
    { 
     return new Run<TActor, TTarget>(actor); 
    } 
} 
+0

Это было первое, что я пробовал. Однако это делает метод расширения неспособным вывести типы, создавая вызов метода, например pete.Run (). Off (); ... который полностью побеждает то, что я пытаюсь сделать. Может быть, то, что я хочу сделать просто, невозможно. –

+0

@JohnKraft Итак, откуда вы ожидаете, чтобы он вывел тип? Метод метода не знает, каким должен быть тип цели. Он не может просто вытащить его из воздуха. – Servy

+2

Точно. :) Как я уже сказал, это может быть невозможно, но я думал, что попрошу людей умнее меня. Это, кажется, довольно распространенный вопрос, хотя, судя по количеству вопросов о переполнении стека, связанных с получением имени класса из экземпляра для перехода к универсальному методу. –