I want to add an AfterRequest event handler to my Bootstrapper.cs that is able to modify the model on the Response after every route is invoked. Is this possible? I don't see any properties on the Response where I could gain access to the Model (if there is one).
Here is my example usage (from Bootstrapper.cs):
protected override void ApplicationStartup(..., IPipelines pipelines)
{
...
pipelines.AfterRequest += ModifyModel;
}
private void ModifyModel(NancyContext ctx)
{
// do things to the response model here
}
If you're still need this functionality you may be interested in an extension I just published on Nuget: https://www.nuget.org/packages/Nancy.ModelPostprocess.Fody. We needed a similar functionality in our project
This will allow you to modify your models after the route has already executed. Do have a look at the description on the Bitbucket page
Please tell me if this suits your needs.
I think is not that simple, you should inspect the ctx.Response.Content in order to know which deserializer is used and what object are you returning, I made a simple example returning a Foo Object Serialized as Json.....
public class MyBootstrapper : Nancy.DefaultNancyBootstrapper
{
protected override void ApplicationStartup(TinyIoC.TinyIoCContainer container, Nancy.Bootstrapper.IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
pipelines.AfterRequest += ModifyModel;
}
private void ModifyModel(NancyContext ctx)
{
Foo foo;
using(var memory = new MemoryStream())
{
ctx.Response.Contents.Invoke(memory);
var str = Encoding.UTF8.GetString(memory.ToArray());
foo = JsonConvert.DeserializeObject<Foo>(str);
}
ctx.Response.Contents = stream =>
{
using (var writer = new StreamWriter(stream))
{
foo.Code = 999;
writer.Write(JsonConvert.SerializeObject(foo));
}
};
}
}
public class HomeModule : Nancy.NancyModule
{
public HomeModule()
{
Get["/"] = parameters => {
return Response.AsJson<Foo>(new Foo { Bar = "Bar" });
};
}
}
public class Foo
{
public string Bar { get; set; }
public int Code { get; set; }
}
After researching this more, this is simply not possible (at least within reason) to do with the Nancy framework as it exists today.
Related
I'm trying to customize some of nUnits behaviour, however I'm constantly hitting a brick wall
because of nUnits heavy use of code reflection. Test methods (and also setup methods etc) are passed all the way down, deep into the framework, and are converted into a delegate at the latest step possible.
The classes I'm interested in are called TestCommands and only there the framework becomes functional.
For reference here is a snippet I found in nUnits source of the TestMethodCommand class which propably is the bread and butter test execution delegate.
public class TestMethodCommand : TestCommand
{
private readonly TestMethod testMethod;
private readonly object[] arguments;
public TestMethodCommand(TestMethod testMethod) : base(testMethod)
{
this.testMethod = testMethod;
this.arguments = testMethod.Arguments;
}
public override TestResult Execute(TestExecutionContext context)
{
object result = InvokeTestMethod(context); // missing a branch deciding about sync vs. async
// missing some code that checks object against "expected result"
return context.CurrentResult;
}
private object InvokeTestMethod(TestExecutionContext context)
{
return testMethod.Method.Invoke(context.TestObject, arguments);
}
}
I'm puzzled why nUnit couldn't wrap the test method into an Func<object> way way sooner and just pass the context along. As it stands for now if I don't have a MethodInfo nUnit can't run it.
In case you wonder, here is an example of a thing I want to do but I ran into the same problem in other instances as well.
[Scenario(When: "Device Registration reads out PCB Type",
Then: "Device Type might change")]
public void Identifier_Changes_Are_Recognized()
{
var changedType = reference.ChangeType(DeviceType.Terminal);
var changedID = reference.ChangeID(123456);
Assert.Multiple(() =>
{
AssertIsSameDevice(reference, changedType);
AssertIsDifferentDevice(reference, changedID);
});
}
This scenario attribute is supposed to print a small description like so.
public void RunBeforeTest()
{
var text = new MultiLineText
("Scenario:",
"\tGiven:\t" + When,
"\tThen:\t" + Then,
"-------------\n"
);
Console.WriteLine(text);
}
I reaaallly want to tell nUnit "Look, here is an action, please run it" but for the time beeing this seems very hard to achieve. Did anyone else here run in these kinds of problems?
Are there possibly ways to achieve what I'm trying to do? Maybe create my own TestCommand, but as I mentioned, these objects only get created very deep into the framework.
OP here (Writing from my home account)
I looked more into this and actually found a working solution:
public class ArbitraryCodeExecutionWrapper : DelegatingTestCommand
{
public ArbitraryCodeExecutionWrapper(TestCommand innerCommand) : base(innerCommand)
{
}
public Action<TestExecutionContext> BeforeTest { get; init; } = _ => { };
public Action<Test, TestResult> AfterTest { get; init; } = (_,_) => { };
public override TestResult Execute(TestExecutionContext context)
{
BeforeTest(context);
var result = innerCommand.Execute(context);
AfterTest(context.CurrentTest, result);
return result;
}
}
public class NUnitTestCommandWrapperAttribute : Attribute, IWrapTestMethod
{
protected virtual void BeforeTest(TestExecutionContext context)
{
}
protected virtual void AfterTest(Test test, TestResult result)
{
}
public TestCommand Wrap(TestCommand command)
=> new ArbitraryCodeExecutionWrapper(command)
{
BeforeTest = BeforeTest,
AfterTest = AfterTest
};
}
public class ScenarioAttribute : NUnitTestCommandWrapperAttribute
{
public string When { get; init; } = "";
public string Then { get; init; } = "";
protected override void BeforeTest(TestExecutionContext context)
{
var text = new MultiLineText
("Scenario:",
"\tGiven:\t" + When,
"\tThen:\t" + Then
);
Console.WriteLine(text);
}
protected override void AfterTest(Test test, TestResult result)
{
Console.WriteLine("After Test");
}
}
[TestFixture]
public class TestCodeExecution
{
[Test]
[Scenario(When = "nUnit Comes here",
Then = "Print Hello World")]
public void Try_Out_Code_Execution()
{
Console.WriteLine("Hello World");
}
}
public class MultiLineText
{
private List<string> items = new();
public static implicit operator string(MultiLineText text) => text.ToString();
public MultiLineText(params string[] lines)
{
items = lines.ToList();
}
public override string ToString() => string.Join("\n", items);
}
I have my code which makes a webservice Call based on type of request.
To do that , I have following code;
public class Client
{
IRequest request;
public Client(string requestType)
{
request = new EnrolmentRequest();
if (requestType == "Enrol")
{
request.DoEnrolment();
}
else if (requestType == "ReEnrol")
{
request.DoReEnrolment();
}
else if (requestType == "DeleteEnrolment")
{
request.DeleteEnrolment();
}
else if (requestType == "UpdateEnrolment")
{
request.UpdateEnrolment();
}
}
}
So as per open close principle, I can subclass like:
Class EnrolmentRequest:IRequest
{
CallService();
}
Class ReEnrolmentRequest:IRequest
{
CallService();
}
Class UpdateEnrolmentRequest:IRequest
{
CallService();
}
Now my client class will look something like this:
public class Client
{
public Client(string requestType)
{
IRequest request;
if (requestType == "Enrol")
{
request = new EnrolmentRequest();
request.CallService();
}
else if (requestType == "ReEnrol")
{
request = new REnrolmentRequest();
request.CallService();
}
else if (requestType == "DeleteEnrolment")
{
request = new UpdateEnrolmentRequest();
request.CallService();
}
else if (requestType == "UpdateEnrolment")
{
request = new UpdateEnrolmentRequest();
request.CallService();
}
}
}
Now , I still have to use if and else , and will have to change my code if there are any new request type.
So, it's definitely, not closed to modification.
Am I missing any thing with respect to SOLID?
Can I use dependency injection, to resolve the types at Run time?
The need to write new code to handle new requirements is not going to disappear. The goal is to not have to change the old code when handling new requirements, and your class structure deals with it.
You can minimize the changes by replacing your chain of conditionals with some other mechanism of creating new instances. For example, you can build a dictionary, or use a dependency injection framework to associate a type with a string.
Here is an implementation without using DI framework:
private static readonly IDictionary<string,Func<IRequest>> ReqTypeMapper =
new Dictionary<string,Func<IRequest>> {
{"Enrol", () => new EnrolmentRequest() }
, {"ReEnrol", () => new ReEnrolmentRequest() }
, ...
};
Now the call will look like this:
Func<IRequest> maker;
if (!ReqTypeMapper.TryGetValue(requestType, out maker)) {
// Cannot find handler for type - exit
return;
}
maker().CallService();
You can't really remove the list of if-else or switch-case statements completely, unless you revert to using reflection. Somewhere in the system you will definately have some sort of dispatching (either using a hard-coded list or through reflection).
Your design however might benefit from a more message based approach, where the incomming requests are message, such as:
class DoEnrolment { /* request values */ }
class DoReenrolment { /* request values */ }
class DeleteEnrolment { /* request values */ }
class UpdateEnrolment { /* request values */ }
This allows you to create a single interface defenition for 'handlers' of such request:
interface IRequestHandler<TRequest> {
void Handle(TRequest request);
}
Your handlers will look as follows:
class DoEnrolmentHandler : IRequestHandler<DoEnrolment> {
public void Handle(DoEnrolment request) { ... }
}
class DoReenrolmentHandler : IRequestHandler<DoReenrolment> {
public void Handle(DoReenrolment request) { ... }
}
class DeleteEnrolmentHandler : IRequestHandler<DeleteEnrolment> {
public void Handle(DeleteEnrolment request) { ... }
}
Advantage of this is that applying cross-cutting concerns is a breeze, since it is very straightforward to define a generic decorator for IRequestHandler<T> that implements something like logging.
This still brings us back to the dispatching of course. Dispatching can be extracted from the client, behind its own abstraction:
interface IRequestDispatcher {
void Dispatch<TRequest>(TRequest request);
}
This allows the client to simply send the request it requires:
// Client
this.dispatcher.Dispatch(new DoEnrolment { EnrolId = id });
An implementation of the request dispatcher might look like this:
class ManualRequestDispatcher : IRequestDispatcher {
public void Dispatch<TRequest>(TRequest request) {
var handler = (IRequestHandler<TRequest>)CreateHandler(typeof(TRequest));
handler.Handle(request);
}
object CreateHandler(Type type) =>
type == typeof(DoEnrolment)? new DoEnrolmentHandler() :
type == typeof(DoReenrolment) ? new DoReenrolment() :
type == typeof(DeleteEnrolment) ? new DeleteEnrolment() :
type == typeof(UpdateEnrolment) ? new UpdateEnrolment() :
ThrowRequestUnknown(type);
object ThrowRequestUnknown(Type type) {
throw new InvalidOperationException("Unknown request " + type.Name);
}
}
If you use a DI Container however, you will be able to batch-register your request handlers with something as follows (depending on the library you use of course):
container.Register(typeof(IRequestHandler<>), assemblies);
And your dispatcher might look as follows:
class ContainerRequestDispatcher : IRequestDispatcher {
private readonly Container container;
public ContainerRequestDispatcher(Container container) {
this.container = container;
}
public void Dispatch<TRequest>(TRequest request) {
var handler = container.GetInstance<IRequestHandler<TRequest>>();
handler.Handle(request);
}
}
You can find more information about this type of design here and here.
You can add simple factory class like below:
public class ServiceFactory : Dictionary<string, Type>
{
public void Register(string typeName, Type serviceType) {
if (this.ContainsKey(typeName)) {
throw new Exception("Type registered");
}
this[typeName] = serviceType;
}
public IRequest Resolve(string typeName) {
if (!this.ContainsKey(typeName)) {
throw new Exception("Type not registered");
}
var type = this[typeName];
var service = Activator.CreateInstance(type);
return service as IRequest;
}
}
then register services in one place like:
var serviceFactory = new ServiceFactory();
serviceFactory.Register("Enrol", typeof(EnrolmentRequest));
serviceFactory.Register("ReEnrol", typeof(REnrolmentRequest));
serviceFactory.Register("DeleteEnrolment", typeof(UpdateEnrolmentRequest));
serviceFactory.Register("UpdateEnrolment", typeof(UpdateEnrolmentRequest));
and call it:
var service = serviceFactory.Resolve(requestType);
service.CallService();
also need to add proper error handling
Good question,
you can achieve your goal using one single method:
var request = (IRequest)Activator.CreateInstance("NameOfYourAssembly", requestType);
request.CallService();
Reflection will help you generating your class instance. After that you can call it without if/else.
Please refer to this link for more information about provided method: https://msdn.microsoft.com/it-it/library/3k6dfxfk(v=vs.110).aspx
Hope this can help
You can use Factory Pattern With RIP (Replace If with Polymorphism) to avoid multiple if-else.
Following code is the sample code according to your Client class :
public enum RequestType : int
{
Enrol = 1,
ReEnrol,
UpdateEnrolment
}
public interface IRequest
{
void CallService();
}
public class EnrolmentRequest : IRequest
{
public void CallService()
{
// Code for EnrolmentRequest
}
}
public class ReEnrolmentRequest : IRequest
{
public void CallService()
{
// Code for ReEnrolmentRequest
}
}
public class UpdateEnrolmentRequest : IRequest
{
public void CallService()
{
// Code for UpdateEnrolmentRequest
}
}
// Factory Class
public class FactoryChoice
{
private IDictionary<RequestType, IRequest> _choices;
public FactoryChoice()
{
_choices = new Dictionary<RequestType, IRequest>
{
{RequestType.Enrol, new EnrolmentRequest() },
{RequestType.ReEnrol, new ReEnrolmentRequest()},
{RequestType.UpdateEnrolment, new UpdateEnrolmentRequest()}
};
}
static public IRequest getChoiceObj(RequestType choice)
{
var factory = new FactoryChoice();
return factory._choices[choice];
}
}
and it will be call like :
IRequest objInvoice = FactoryChoice.getChoiceObj(RequestType.ReEnrol);
objInvoice.CallService();
Here, main things happened in the FactoryChoice class constructor. That's why someone called it smart constructor. This way you can avoid multilpe if-else or switch-case.
To know the basic of RIP you can check my slide here.
you can use autofac keyed or named service..
public enum OperationType
{
Enrol,
ReEnrol,
DeleteEnrolment,
UpdateEnrolment
}
//register types
builder.RegisterType<EnrolmentRequest>().Keyed<IRequest>(OperationType.Enrol);
builder.RegisterType<ReEnrolmentRequest>().Keyed<IRequest>(OperationType.ReEnrol);
builder.RegisterType<UpdateEnrolmentRequest>().Keyed<IRequest>(OperationType.DeleteEnrolment | OperationType.UpdateEnrolment);
// resolve by operationType enum
var request = container.ResolveKeyed<IRequest>(OperationType.Enrol);
Is there an elegant (or any) way to achieve following in C#?
Let's have a class ItemBase (further derivable to Item1, Item2...), which does not allow direct instantiation (non-public construction) - to prevent user to create any 'untracked' instance of Item*.
Let's have a non-static class Manager, whose instances (multiple ones allowed) only can create and provide instances of Item* (because they keep track of produced instances and do some additional work).
Let's have an optional requirement: The Manager instances would like to manipulate non-public members of the managed Item instances (similar like the Manager would be a friend of Item*).
It would be nice if the Manager is not forced to be derivation of Item*.
It would be nice if there is as little reflection as possible.
Notes:
If possible, please consider this as a question raising from process of thinking how to implement particular problem solution in a best and elegant way. I would like it to be general and no, I don't have sources and yes, I have already tried some variants, but none of them satisfied my needs. Thank you.
As far as I know, there is no acceptable friend alternative (any of internal and InternalsVisibleToAttribute seems to be good), so the ItemBase just provides the 'special' (but public) modification methods and the user must be aware, these methods are not for him :o(
I like this solution, but I'm not able to invent, how to allow multiple Manager instances using it.
I think this might answer your problem :
public class ItemBase
{
protected ItemBase()
{
}
public void PublicMethod() { }
public int PublicProperty { get; set; }
}
public class Factory
{
private class PrivateItemBase : ItemBase
{
public void PrivateMethod() { }
public int PrivateProperty { get; set; }
}
public Factory(int id)
{
}
public IEnumerable<ItemBase> Items { get; private set; }
public ItemBase CreateItem()
{
PrivateItemBase rValue = new PrivateItemBase();
rValue.PrivateMethod();
rValue.PrivateProperty = 4;
return rValue;
}
}
Ok, giving up. If this might help to fully understand the purpose, there is the less bad solution I've (currently) ended up. Passing the creation functions is done via static constructors (which are not accessible by the users), unfortunately the ugly thing is their invocation...
Any idea how to make it better?
The item definitions:
namespace SpecialFactory
{
public enum ItemType
{
Item1,
Item2,
// ... Anyone deriving the Item* should add an item here
}
public abstract class ItemBase
{
public abstract ItemType Id {get;}
public static void RegisterAllCreators()
{
// Force static constructors invocation
var it = Item1.ClassId | Item2.ClassId; // Anyone deriving the Item* should ensure invocation of Manager.RegisterCreator
}
}
public class Item1 : ItemBase
{
static Item1()
{
Manager.RegisterCreator(ItemType.Item1, () => new Item1());
}
protected Item1()
{
}
public static ItemType ClassId => ItemType.Item1;
public override ItemType Id => ClassId;
}
public class Item2 : ItemBase
{
static Item2()
{
Manager.RegisterCreator(ItemType.Item2, () => new Item2());
}
protected Item2()
{
}
public static ItemType ClassId => ItemType.Item2;
public override ItemType Id => ClassId;
}
}
The manager:
namespace SpecialFactory
{
public class Manager
{
static Manager()
{
ItemBase.RegisterAllCreators();
}
protected static Dictionary<ItemType, Func<ItemBase>> creators = new Dictionary<ItemType, Func<ItemBase>>();
protected readonly List<ItemBase> managedItems = new List<ItemBase>();
protected ItemBase CreateItem(ItemType type)
{
ItemBase item = null;
if (creators.ContainsKey(type))
{
if ((item = creators[type]()) != null)
managedItems.Add(item);
}
return item;
}
public static void RegisterCreator(ItemType type, Func<ItemBase> creator)
{
if (!creators.ContainsKey(type))
creators[type] = creator;
}
public Manager()
{
}
public ItemBase Test(ItemType type)
{
// var notAllowed = new Item1();
var allowed = CreateItem(type);
return allowed;
}
}
}
The test:
namespace SpecialFactory
{
class Program
{
static void Main(string[] args)
{
var m1 = new Manager();
var m2 = new Manager();
var i1 = m1.Test(ItemType.Item1);
var i2 = m2.Test(ItemType.Item2);
}
}
}
I'm using the System.Composition namespace from the MEF for web and Windows Store apps NuGet package in a new ASP.NET MVC4 project.
I've read that in MEF2 you no longer use Lazy<IExtension, IExtensionMetadata>, but now you must provide a concrete type for the metadata view (and possibly use ExportFactory<> instead of Lazy<> ?).
However, I can't find any examples of how this should all work - just a few mentions of using a concrete type instead of an interface.
I've tried a few things, but keep getting the following error - "Export metadata for 'AccountID' is missing and no default value was supplied".
My code...
Creating the container (in Global.asax or App_Start folder):
// Get assemblies that will be providing imports and exports
var assemblies = GetAssemblies();
// Get conventions that will be used to find imports and exports
var conventions = GetConventions();
var container = new ContainerConfiguration().WithAssemblies(assemblies, conventions).CreateContainer();
// Create and apply a MefControllerFactory so controllers can be composed
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
GetConventions() method:
private static ConventionBuilder GetConventions()
{
var conventionBuilder = new ConventionBuilder();
conventionBuilder.ForTypesDerivedFrom<IController>().Export();
conventionBuilder.ForTypesDerivedFrom<IExtension>().Export<IExtension>();
conventionBuilder.ForTypesMatching(t => t.Namespace != null && t.Namespace.EndsWith(".Parts")).Export().ExportInterfaces();
return conventionBuilder;
}
IExtension.cs:
public interface IExtension
{
void DoWork();
}
ExtensionMetadata.cs:
public class ExtensionMetadata
{
public int AccountID { get; set; }
}
ExtensionA.cs (same as ExtensionB.cs):
public void DoWork()
{
System.Diagnostics.Debug.WriteLine("ExtensionA doing work..");
}
ExtensionManager.cs:
public class ExtensionManager
{
private IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> _extensions;
public ExtensionManager(IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> extensions)
{
_extensions = extensions;
}
public void DoWork(int accountID)
{
foreach (var extension in _extensions)
{
if (extension.Metadata.AccountID == accountID)
{
extension.DoWork();
}
}
}
}
I think I'm missing something quite major here. Basically I want to lazily import all Extensions, check their metadata and if a condition is fulfilled have that extension do something.
Would really appreciate your feedback or any links to sample code / tutorials that cover my scenario.
Many thanks!
I think I've worked it out after reading this SO question.
I created a Metadata Attribute:
[MetadataAttribute]
public class ExtensionMetadataAttribute : ExportAttribute, IExtensionMetadata
{
public int AccountID { get; set; }
public ExtensionMetadataAttribute(int accountID) : base(typeof (IExtension))
{
AccountID = accountID;
}
}
Then modified ExtensionA.cs:
[ExtensionMetadata(1)]
public class ExtensionA : IExtension
{
public void DoWork()
{
System.Diagnostics.Debug.WriteLine("ExtensionA doing work..");
}
}
And now ExtensionManager.cs looks like this:
public class ExtensionManager : IExtensionManager
{
private readonly IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> _extensions;
public ExtensionManager(IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> extensions)
{
_extensions = extensions;
}
public void DoWork(int accountID)
{
foreach (var extension in _extensions)
{
if (extension.Metadata.AccountID == accountID)
{
using (var foo = extension.CreateExport())
{
foo.Value.DoWork();
}
}
}
}
}
This seems to do the trick, but I would still be interested in any feedback re best practices, performance issues etc.
Thanks!
Suppose I have a base class named Visitor, and it has 2 subclass Subscriber and NonSubscriber.
At first a visitor is start off from a NonSubscriber, i.e.
NonSubscriber mary = new NonSubscriber();
Then later on this "mary" subscribed to some services, and I want to change the type of "mary" to Subscriber.
What is the conventional way to do that?
can't do that. sorry. C# is not a dynamic language.
You will have to create a new mary = new Subscriber(); and copy all relevant properties.
But a better approach might be to model it differently: Give Visitor a list of subscriptions. An empty list means a NonSubscriber.
You cant do this type of conversion.
What you should do is treat mary as a visitor, and when time arrives, create a new instance of "subscriber":
Visitor mary = new NonSubscriber();
// Do some Visitor operations
...
// Now mary is a Subscriber
mary = new Subscriber();
You could use the GOF design patterns State or Strategy to model such an behaviour. Using these patterns, it seems during runtime as if the class of the objects has been changed.
It seems that you have some design problems. I think that it would be better to redesign your code like:
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;
}
}
You cannot change the type of a variable at runtime. You need to create a new instance.
mary = new Subscriber();
Create a Subscriber constructor that takes a NonSubscriber object as a parameter, or create a method on the NonSubscriber object that returns a Subscriber to save you having to writer the mappping code in multiple places.
It seems like you are encoding information incorrectly into your class hierarchy. It would make more sense to use a different pattern than sub classing here. For example, use only one class (visitor, or perhaps you could name it potential subscriber, whatever seems appropriate) and encode information on the services the object is subscribed to, moving the dynamically changing behavior behind a "Strategy" pattern or some such. There's very little detail in your example, but one thing you could do in C# is to make a "subscriber" property which would change the behavior of the object when the state of the property was changed.
Here's a contrived 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();
}
}
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 :)
Adding to the other answers and your comment, you indeed can use the state pattern for your purpose, it would go 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'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"; }
}
}