2010-08-07 4 views
1

Учитывая эти C# классы (генерируется WCF, я не могу изменить эти):Производные классы в качестве возвращаемого значения

public SysState GetSysState(); 

public class SysState { /* nothing much here */} 
public class Normal : SysState { /* properties & methods */ } 
public class Foobar : SysState { /* different properties & methods */ } 

Мой код (в настоящее время):

SysState result = GetSysState(); 

if (result is Normal) HandleNormal((Normal) result); 

if (result is Foobar) HandleFoobar((Foobar) result); 

Мой вопрос: Я все время чувствую, что мне не хватает чего-то очевидного, что я не должен явно проверять тип. Имею ли я старший момент?

ответ

1

Используйте виртуальный метод. Поместите свой код в классы, на которых они работают, а не на какой-то код, который получает ссылку на класс.

public class SysState { 
    /* nothing much here, except...: */ 
    public abstract virtual void DoSomething(); 
} 

public class Normal : SysState { 
    /* properties & methods */ 
    public override void DoSomething() 
    { 
    // ... 
    } 
} 

public class Foobar : SysState { 
    /* different properties & methods */ 
    public override void DoSomething() 
    { 
    // ... 
    } 
} 

SysState result = SomeFunctionThatReturnsObjectDerivedFromSysState(); 

result.DoSomething(); 

Это выполнит метод DoSomething производного класса. Это называется полиморфизмом и является наиболее естественным (и некоторые утверждают, что использование наследования только ).

Обратите внимание, что SysState.DoSomething не обязательно должен быть абстрактным для этого, но он должен быть виртуальным.

+0

+1 Я попробую это, спасибо. – egrunin

+0

@egrunin: Если вы абсолютно не можете изменить классы вообще, то вы, очевидно, не сможете этого сделать, и вам придётся использовать «если это тип ... еще, если это другой тип ...» , Однако вы можете написать свои собственные классы-оболочки на стороне клиента, чтобы позаботиться об этой проблеме для вас. Классы-оболочки будут иметь эти классы в качестве их кишок и обеспечить открытый интерфейс, который выполняет полиморфизм. Вам все равно понадобится «if this type, then ...», но вам нужно будет написать его один раз, где он преобразует типы в ваши обертки. –

0

Вы можете попробовать сочетание handleX и размещение Handle в SysState и наиважнейший его в обоих Normal и Foobar для выполнения конкретных задач. Это может быть не идеальное решение, но оно выглядело бы довольно аккуратно. Если вам нужно вводить данные из других источников, передайте их в качестве параметров?

public class SysState 
{ 
    public bool Process(Information info) 
    { 
     return (info.Good); 
    } 
} 

public class Normal 
{ 
    public bool Process(Information info) 
    { 
     return doStuff(); 
    } 
} 

public class Foobar 
{ 
    public bool Process(Information info) 
    { 
     return diePainfully(); 
    } 
} 

Очевидно, просто пример, не зная, что делать HandleNormal и HandleFoobar, но он может работать хорошо.

+0

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

+0

Ах. Ну, тогда это не сработает. Не могли бы вы применить их к общему типу, который имеет функцию обработки для обработки любых различий? – ssube

+5

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

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