2010-03-23 2 views
6

Предположим, у меня есть базовый класс с именем Visitor, и он имеет 2 подкласса Subscriber и NonSubscriber.Как динамически изменить класс объекта на C#?

В первый посетитель начать с NonSubscriber, т.е.

NonSubscriber mary = new NonSubscriber(); 

Тогда позже на этом «МЭРИ» подписался на некоторые услуги, и я хочу, чтобы изменить тип «МЭРИ» Абоненту.

Что такое обычный способ сделать это?

ответ

6

не можем этого сделать. Прости. C# не является динамическим языком.

+4

Вы, однако, можете, вероятно, использовать шаблон «State», как описано в GoF. но вам не нужно менять тип класса/объекта! – cruizer

+0

даже с динамическим langauge. ИЗМЕНЕНИЕ ТИПА ОБЪЕКТА не всегда возможно. – TomTom

+0

Большое спасибо за предложение шаблона «State» ... Wot Я пытаюсь сделать здесь, чтобы использовать подклассы и наследование, чтобы каждый раз, когда страница была визуализирована, вызывается соответствующий производный метод. Например, для не-подписчиков я хочу показать ссылку «Присоединиться сейчас». , тогда как для подписчиков я хочу показать ссылку на «Сегодняшняя специальность», а остальная часть страницы является общей для всех посетителей. – Chris

4

Вам необходимо будет создать новый mary = new Subscriber(); и скопировать все соответствующие свойства.

Но лучший подход может заключаться в моделировании по-разному: дайте Visitor список подписки. Пустой список означает NonSubscriber.

1

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

mary = new Subscriber(); 
4

Вы не можете сделать этот тип преобразования. Что вы должны сделать, это лакомство мэри в качестве гостя, и когда придет время, создать новый экземпляр «абонент»:

Visitor mary = new NonSubscriber(); 
// Do some Visitor operations 
... 
// Now mary is a Subscriber 
mary = new Subscriber(); 
+0

Точно! это то, что я собирался сказать. :) – albertjan

0

Создать Subscriber конструктор, который принимает NonSubscriber объекта в качестве параметра, или создать метод на объекте NonSubscriber, который возвращает Subscriber, чтобы сохранить вам возможность записывать код сопоставления в нескольких местах.

0

Похоже, что вы неправильно кодируете информацию в свою иерархию классов. Было бы разумнее использовать другой шаблон, чем подкласс. Например, используйте только один класс (посетитель, или, возможно, вы можете назвать его потенциальным подписчиком, что бы ни было уместным) и кодировать информацию об услугах, на которые подписан данный объект, перемещая динамически изменяющееся поведение за шаблоном «Стратегия» или некоторые из них. В вашем примере очень мало деталей, но одна вещь, которую вы можете сделать на C#, - это создать свойство «подписчика», которое изменило бы поведение объекта при изменении состояния свойства.

Вот надуманный несколько связанных пример:

class Price 
{ 
    private int priceInCents; 
    private bool displayCents; 

    private Func<string> displayFunction; 

    public Price(int dollars, int cents) 
    { 
     priceInCents = dollars*100 + cents; 
     DisplayCents = true; 
    } 

    public bool DisplayCents 
    { 
     get { return displayCents; } 
     set 
     { 
      displayCents = value; 
      if (displayCents) 
      { 
       this.displayFunction =() => String.Format("{0}.{1}", priceInCents/100, priceInCents % 100); 
      } 
      else 
      { 
       this.displayFunction =() => (priceInCents/100).ToString(); 
      } 
     } 
    } 

    public string ToString() 
    { 
     return this.displayFunction(); 
    } 
} 
1

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

class Visitor 
{ 
    private bool isSubscriber = false; 

    public bool IsSubscriber 
    { 
     get { return isSubscriber; } 
    } 

    public void Subscribe() 
    { 
     // do some subscribing stuff 
     isSubscriber = true; 
    } 

    public void Unsubscribe() 
    { 
     // do some unsubscribing stuff 
     isSubscriber = false; 
    } 
} 
3

Вы можете использовать шаблоны проектирования GOF государственных или Стратегия для моделирования такого поведения. Используя эти шаблоны, во время выполнения кажется, что класс объектов был изменен.

0
public class User 
{ 
    public Subscription Subscription { get; set; } 
    public void HandleSubscription() 
    { 
     Subscription.Method(); 
    } 
} 

public abstract class SubscriptionType 
{ 
    public abstract void Method(); 
} 

public class NoSubscription : SubscriptionType 
{ 
    public override void Method() 
    { 
    // Do stuff for non subscribers 
    } 
} 

public class ServiceSubscription : SubscriptionType 
{ 
    public override void Method() 
    { 
    // Do stuff for service subscribers 
    } 
} 

public class Service2Subscription : SubscriptionType 
{ 
    public override void Method() 
    { 
    // Do stuff for service2 subscribers 
    } 
} 

Подумайте код объясняет мой ответ :)

0

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

public class MyProgram 
{ 
    public void Run() 
    { 
     Visitor v = new Visitor("Mary"); 

     Debug.Assert(v.SubscriptionLinkText == "Join now"); 

     v.IsSubscribed = true; 
     Debug.Assert(v.SubscriptionLinkText == "Today's special"); 

     v.IsSubscribed = false; 
     Debug.Assert(v.SubscriptionLinkText == "Join now"); 
    } 
} 

public class Visitor 
{ 
    public string Name { get; set; } 

    private bool _isSubscribed; 
    public bool IsSubscribed 
    { 
     get { return this._isSubscribed; } 

     set 
     { 
      if (value != this._isSubscribed) 
      { 
       this._isSubscribed = value; 
       this.OnSubscriptionChanged(); 
      } 
     } 
    } 

    private SubscriptionBase _subscription; 

    public string SubscriptionLinkText 
    { 
     get { return this._subscription.LinkText; } 
    } 

    public Visitor(string name) 
    { 
     this.Name = name; 
     this._isSubscribed = false; 
     this.OnSubscriptionChanged(); 
    } 

    private void OnSubscriptionChanged() 
    { 
     // Consider also defining an event and raising it here 

     this._subscription = 
      SubscriptionBase.GetSubscription(this.IsSubscribed); 
    } 
} 

abstract public class SubscriptionBase 
{ 
    // Factory method to get instance 
    static public SubscriptionBase GetSubscription(bool isSubscribed) 
    { 
     return isSubscribed ? 
       new Subscription() as SubscriptionBase 
       : new NoSubscription() as SubscriptionBase; 
    } 

    abstract public string LinkText { get; } 
} 

public class Subscription : SubscriptionBase 
{ 
    public override string LinkText 
    { 
     get { return "Today's Special"; } 
    } 
} 

public class NoSubscription : SubscriptionBase 
{ 
    public override string LinkText 
    { 
     get { return "Join now"; } 
    } 
} 
Смежные вопросы