How to dynamically change an object class in C #?

Suppose I have a base class called Visitor and it has 2 subclasses Subscriber and NonSubscriber.

First, the visitor starts with NonSubscriber, i.e.

NonSubscriber mary = new NonSubscriber(); 

Then later this β€œmary” subscribed to some services, and I want to change the type of β€œmary” to Subscriber.

What is the usual way to do this?

+6
c #
source share
10 answers

can't do that. Sorry. C # is not a dynamic language.

+6
source share

You will need to create a new mary = new Subscriber(); and copy all the relevant properties.

But a better approach might be to model it differently: give Visitor a subscription list. An empty list means NonSubscriber.

+4
source share

You cannot do this type of conversion. What you have to do is handle mary as a visitor, and when the time comes, create a new instance of the β€œsubscriber”:

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

You can use GOF State or Strategy design templates to model this behavior. Using these templates, at runtime it seems that the feature class has been changed.

+3
source share

You cannot change the type of a variable at runtime. You need to create a new instance.

 mary = new Subscriber(); 
+1
source share

It seems like you have design issues. I think it would be better to reverse engineer your code, for example:

 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; } } 
+1
source share

Create a Subscriber constructor that takes a NonSubscriber object as a parameter, or create a method for a NonSubscriber object that returns a Subscriber to save you to write the mapping code in several places.

0
source share

It seems that you are not correctly encoding information into your class hierarchy. It would be wiser to use a different template than a subclass. For example, use only one class (a visitor, or perhaps you can call it a potential subscriber, whatever is appropriate) and encode information about the services that this object subscribes to by moving the dynamically changing behavior behind the "Strategy" template or some of them. There are very few details in your example, but one thing you can do in C # is to create a β€œsubscriber” property that would change the behavior of the object when the state of the property changes.

Here's a far-fetched somewhat related example:

 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(); } } 
0
source share
 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 } } 

Think the code explains my answer :)

0
source share

Adding to the other answers and your comment, you can really use the status template for your purpose, it will look something like this:

 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 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 Special"; } } } public class NoSubscription : SubscriptionBase { public override string LinkText { get { return "Join now"; } } } 
0
source share

All Articles