Strategy Pattern or Interface? - c#-4.0

I'm looking to abstract a helper method. The method needs to be able to take in an object, do things with it depending on the type of object, and return a value. Would it be better to do something like this:
interface ICanDo
{
string DoSomething();
}
string DoThings(ICanDo mything)
{
return mything.DoSomething();
}
Or is it better to do something like this:
interface IStrategy
{
string DoSomething(object o);
}
string DoThings(object mything, IStrategy strategy)
{
return strategy.DoSomething(mything);
}
Is the latter even using a strategy pattern, since the strategy isn't being built into the class?
Is there a better way to do this I'm not thinking of? Would it be better to build the strategy into the class, using a wrapper for any class that needs to have DoThings run on it?
Sorry--I'm new to this pattern and trying to figure out where and how to use it best.
This is what I ended up putting together. I'm unsure if this follows good development principles.
class IndexWrapper
{
public interface IDocumentable
{
Document BuildDocument();
}
public interface IDocumentBuilder
{
Type SupportedType { get; }
Document BuildDocument(object o);
}
public class StringDocumentBuilder : IDocumentBuilder
{
public Type SupportedType { get { return typeof(string); } }
public Document BuildDocument(object o)
{
Document doc = new Document();
doc.Add(new Field("string", o as string, Field.Store.YES, Field.Index.ANALYZED));
return doc;
}
}
public static class IndexableFactory
{
public static IDocumentable GetIndexableObject(object o)
{
return GetIndexableObject(o, DocumentBuilderFactory.GetBuilder(o));
}
public static IDocumentable GetIndexableObject(object o, IDocumentBuilder builder)
{
return new IndexableObject(o, builder);
}
}
public static class DocumentBuilderFactory
{
private static List<IDocumentBuilder> _builders = new List<IDocumentBuilder>();
public static IDocumentBuilder GetBuilder(object o)
{
if (_builders.Count == 0)
{
_builders = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => typeof(IDocumentBuilder).IsAssignableFrom(type) && type.IsClass)
.Select(type => Activator.CreateInstance(type))
.Cast<IDocumentBuilder>()
.ToList();
}
return _builders.Where(builder => builder.SupportedType.IsAssignableFrom(o.GetType())).FirstOrDefault();
}
}
private class IndexableObject : IDocumentable
{
object _o;
IDocumentBuilder _builder;
public IndexableObject(object o) : this(o, DocumentBuilderFactory.GetBuilder(o)) { }
public IndexableObject(object o, IDocumentBuilder builder)
{
_o = o;
_builder = builder;
}
virtual public Document BuildDocument()
{
return _builder.BuildDocument(_o);
}
}
}

When in doubt, keep the KISS mantra in your mind - Keep It Short and Simple. Patterns can be very useful, but often they're only useful in specific cases and add unnecessary complexity otherwise.
In my experience, the strategy pattern is useful for when you have multiple different backends to choose from for a class. For example, say you have a logging class that your program uses to print debug information. Maybe in some cases, you want to log to a file. Maybe you'd like to log to a console. Perhaps you'd even like to log to a remote server with a proprietary protocol you company made!
So, your logging class may look like this:
interface IOutputWriter
{
void WriteLn(string message);
}
class ConsoleWriter : IOutputWriter
{
public ConsoleWriter()
{
}
public void WriteLn(string message)
{
Console.WriteLine(message);
}
}
class NetworkWriter : IOutputWriter
{
public NetworkWriter()
{
}
public void WriteLn(string message)
{
//Crazy propietary server protocol action
}
}
class Logger
{
IOutputWriter writer;
public Logger(IOutputWriter writer)
{
this.writer = writer;
}
public void Log(string message)
{
writer.WriteLn(message + "Date");
}
}
With the end result that your program code looks like this:
class Program
{
static void Main(string[] args)
{
Logger logger = new Logger(new ConsoleWriter());
logger.Log("Test");
}
}
The benefit is that if you want to use your crazy networking protocol, you can do it without even looking at the logging class. You just have to make a new class with your IOutputWriter interface and tell your logger to use your custom backend. The strategy pattern is essentially defining reusable interfaces and then using those interfaces to decouple algorithms from each other.

Related

C# Class implementation with generics

Hi everyone I am studying C# but ran into some compiler errors:
I am getting the error: 'LinkedList' does not implement interface member 'IEnumerable.GetEnumerator()'
I think I did.
Below is the code:
using System;
using System.Collections.Generic;
namespace LinkedListGenericsExample
{
public class LinkedListNode<T>
{
//constructor
public LinkedListNode(T value)
{
//code here
}
//code here
}
//LinkedList class with generics. It inherit the IEnumerable class with
//generics. Should I use IEnumerable or IEnumerable<T>?
public class LinkedList<T>: IEnumerable<T>
{
//code here
}
public LinkedListNode<T> AddLast(T node)
{
//code here
}
public IEnumerator<T> GetEnumerator()
{
//code here
}
//here I think the GetEnumerator() method is implemented
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
//Trying this but not working. Also I am confused.
/*
IEnumerator IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
*/
//Main() below
}
I am using the Visual Studio Code to compile the code.
Error ecountered:
'LinkedList' does not implement interface member 'IEnumerable.GetEnumerator()'
Using the generic type 'IEnumerator' requires 1 type arguments
Using the generic type 'IEnumerable' requreis 1 type arguments
'IEnumerable' in explicit interface declaration is not an interface
Question:
1) Should I inherit the IEnumerable class or IEnumerable class with generic?
2) How can I implement the "IEnumerable.GetEnumerator()" It looks like the compiler is not recognized my GetEnumerator() implementation but I am not sure why....
Need some help here. Thank you!
Updating the complete code below. It works!!
using System;
using System.Collections; //using System.Collections instead
namespace LinkedListGenericsExample
{
//Linked list node class in Generics form
public class LinkedListNode<T>
{
//LinkedListNode constructor
public LinkedListNode(T value)
{
this.Value = value;
}
public T Value;
public LinkedListNode<T> Next {get; internal set;}
public LinkedListNode<T> Prev {get; internal set;}
}
public class LinkedList<T>: IEnumerable
{
public LinkedListNode<T> First {get; private set;}
public LinkedListNode<T> Last {get; private set;}
public LinkedListNode<T> AddLast(T node)
{
var newNode = new LinkedListNode<T>(node);
if (First == null)
{
First = newNode;
Last = First;
}
else
{
Last.Next = newNode;
Last = newNode;
}
return newNode;
}
public IEnumerator GetEnumerator()
{
LinkedListNode<T> current = First;
while(current != null)
{
yield return current.Value;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/*
IEnumerator IEnumerable<T>.GetEnumerator()
{
}
*/
}
class Program
{
static void Main(string[] args)
{
//Console.WriteLine("Hello World!");
var list2 = new LinkedList<int>();
var list3 = new LinkedList<String>();
list2.AddLast(1);
list2.AddLast(3);
list2.AddLast(5);
//Go throuhg entire list of numbers
foreach(int i in list2)
{
Console.WriteLine(i);
}
Console.WriteLine();
list3.AddLast("2");
list3.AddLast("four");
list3.AddLast("foo");
//Go through entire list of strings
foreach(string s in list3)
{
Console.WriteLine(s);
}
}
}
}
Regarding your two questions, here are 2 cents.
1. I would suggest you implement the generic version. This would ensure type-safety and other benefits. You can read more on advantages of generics in this link. . Since you are learning C#, it would be a good idea to read about it.
Your implementation looks good.Please add reference to System.Collections namespace to your code for fixing the compile errors.
using System.Collections;

Execute an objects method without making a new instance

How can I execute Print from within TestObject?
class Program
{
private int Value;
static void Main()
{
TestObject test = new TestObject();
Program p1 = new Program();
Program p2 = new Program();
p1.Value = 1;
p2.Value = 2;
p1.Print();
p2.Print();
}
private void Print()
{
Console.Write(Value.ToString());
Console.ReadKey();
}
}
class TestObject
{
// How to execute p1.Print here?
}
There are multiple ways to do this:
Pass Program directly to TestObject
Pros:
Simple change
Cons:
You will have to make Print public
You will expose other things in Program
You're coupling TestObject to Program directly
Here's sample code:
class Program
{
static void Main()
{
TestObject test = new TestObject(this);
}
public void Print()
{
Console.Write(Value.ToString());
Console.ReadKey();
}
}
class TestObject
{
public TestObject(Program p)
{
p.Print();
}
}
Pass a delegate to TestObject
Pros:
Simple change
Doesn't have to make Print public
Only exposes 1 method to TestObject
Cons:
The coupling is TestObject wants to do something, not TestObject wants access to something that does something
Here's sample code:
class Program
{
static void Main()
{
TestObject test = new TestObject(() => Print());
}
private void Print()
{
Console.Write(Value.ToString());
Console.ReadKey();
}
}
class TestObject
{
public TestObject(Action print)
{
print();
}
}
Implement an interface in Program and pass it to TestObject
Pros:
Only exposes what the interface exposes
Easier to implement other places (better to say "need this interface" than "needs a delegate", clearer contract specification)
No coupling to a specific type, coupling is to any object that meets certain criteria - implements an interface
Cons:
None relevant (in my opinion)
Here's sample code:
interface IPrintable
{
void Print();
}
class Program : IPrintable
{
static void Main()
{
TestObject test = new TestObject(this);
}
public void Print()
{
Console.Write(Value.ToString());
Console.ReadKey();
}
}
class TestObject
{
public TestObject(IPrintable p)
{
p.Print();
}
}
Conclusion: My advice would be to pick the interface way. Clearer design, easier to extend without having multiple delegates being passed around.

Is it normal to return actor's proxy from service

I have some service which accepts some data and then, as I think, should return an actor initialized with some values.
public class MyService : StatefulService, IMyService
{
public IMyActor DoThings(Data data)
{
var actor = ActorProxy.Create<IMyActor>(new ActorId(Guid.NewGuid()));
actor.Init(data);
//some other things
return actor;
}
}
Another service would do this:
var service = ServiceProxy.Create<ICommandBrokerService>(new Uri("fabric:/App"), ServicePartitionKey.Singleton);
var actor = service.DoThings(data);
var state = actor.GetState();
//...
So, is it okay to return an actor in such a way, or should I return actor's id and request a proxy on a call sight?
UPD:
According to a #LoekD 's answer I did a wrapper to be a little type-safety.
[DataContract(Name = "ActorReferenceOf{0}Wrapper")]
public class ActorReferenceWrapper<T>
{
[DataMember]
public ActorReference ActorReference { get; private set; }
public ActorReferenceWrapper(ActorReference actorRef)
{
ActorReference = actorRef ?? throw new ArgumentNullException();
}
public T Bind()
{
return (T)ActorReference.Bind(typeof(T));
}
public IActorService GetActorService(IActorProxyFactory serviceProxy=null)
{
return ActorReference.GetActorService(serviceProxy);
}
public TService GetActorService<TService>(IActorProxyFactory serviceProxyFactory) where TService : IActorService
{
return serviceProxyFactory.CreateActorServiceProxy<TService>(ActorReference.ServiceUri,
ActorReference.ActorId);
}
public static implicit operator ActorReference(ActorReferenceWrapper<T> actorRef)
{
return actorRef.ActorReference;
}
public static explicit operator ActorReferenceWrapper<T>(ActorReference actorReference)
{
return new ActorReferenceWrapper<T>(actorReference);
}
}
No, the types used in SF remoting must be DataContractSerializable. The contracts you use can only have fields and properties, no methods.
So, instead of returning the proxy, return an Actor Reference.
Next, use Bind to create a proxy from it.

How is IClock resolved with SystemClock in this example?

I am trying to learn IOC principle from this screencast
Inversion of Control from First Principles - Top Gear Style
I tried do as per screencast but i get an error while AutomaticFactory try create an object of AutoCue. AutoCue class has contructor which takes IClock and not SystemClock. But my question is , in screencast IClock is resolved with SystemClock while inside AutomaticFactory .But in my code , IClock does not get resolved . Am i missing something ?
class Program
{
static void Main(string[] args)
{
//var clarkson = new Clarkson(new AutoCue(new SystemClock()), new Megaphone());
//var clarkson = ClarksonFactory.SpawnOne();
var clarkson = (Clarkson)AutomaticFactory.GetOne(typeof(Clarkson));
clarkson.SaySomething();
Console.Read();
}
}
public class AutomaticFactory
{
public static object GetOne(Type type)
{
var constructor = type.GetConstructors().Single();
var parameters = constructor.GetParameters();
if (!parameters.Any()) return Activator.CreateInstance(type);
var args = new List<object>();
foreach(var parameter in parameters)
{
var arg = GetOne(parameter.ParameterType);
args.Add(arg);
}
var result = Activator.CreateInstance(type, args.ToArray());
return result;
}
}
public class Clarkson
{
private readonly AutoCue _autocue;
private readonly Megaphone _megaphone;
public Clarkson(AutoCue autocue,Megaphone megaphone)
{
_autocue = autocue;
_megaphone =megaphone;
}
public void SaySomething()
{
var message = _autocue.GetCue();
_megaphone.Shout(message);
}
}
public class Megaphone
{
public void Shout(string message)
{
Console.WriteLine(message);
}
}
public interface IClock
{
DateTime Now { get; }
}
public class SystemClock : IClock
{
public DateTime Now { get { return DateTime.Now; } }
}
public class AutoCue
{
private readonly IClock _clock;
public AutoCue(IClock clock)
{
_clock = clock;
}
public string GetCue()
{
DateTime now = _clock.Now;
if (now.DayOfWeek == DayOfWeek.Sunday)
{
return "Its a sunday!";
}
else
{
return "I have to work!";
}
}
}
What you basically implemented is a small IoC container that is able to auto-wire object graphs. But your implementation is only able to create object graphs of concrete objects. This makes your code violate the Dependency Inversion Principle.
What's missing from the implementation is some sort of Register method that tells your AutomaticFactory that when confronted with an abstraction, it should resolve the registered implementation. That could look as follows:
private static readonly Dictionary<Type, Type> registrations =
new Dictionary<Type, Type>();
public static void Register<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
registrations.Add(typeof(TService), typeof(TImplementation));
}
No you will have to do an adjustment to the GetOne method as well. You can add the following code at the start of the GetOne method:
if (registrations.ContainsKey(type))
{
type = registrations[type];
}
That will ensure that if the supplied type is registered in the AutomaticFactory as TService, the mapped TImplementation will be used and the factory will continue using this implementation as the type to build up.
This does mean however that you now have to explicitly register the mapping between IClock and SystemClock (which is a quite natural thing to do if you're working with an IoC container). You must make this mapping before the first instance is resolved from the AutomaticFactory. So you should add the following line to to the beginning of the Main method:
AutomaticFactory.Register<IClock, SystemClock>();

NServiceBus Configuration with Custom Container

I am trying to re-use the service registrations in an assembly that I use through a few services in my solution. I follow the example listed from the NServiceBus website to implement the solution. When following that, unless I add the IWantCustomInitialization interface, my Init method (and IoC container implementation) appears not to function. When I have that interface implemented, I get exceptions (listed in SO questions here and here). I can't seem to get it to work that there are no exceptions AND the dependencies in my MessageHandler are being populated properly. Here is my current EndpointConfig implementation.
[EndpointSLA("00:00:30")]
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, UsingTransport<Msmq>, INeedInitialization {
public void Init() {
Configure.With().ObjectBuilderAdapter();
}
}
public class ObjectBuilderAdapter : IContainer {
readonly IDependencyInjector injector;
public ObjectBuilderAdapter(IDependencyInjectionBuilder dependencyInjectionBuilder) {
injector = dependencyInjectionBuilder.Create(); //This method does all the common service registrations that I am trying to re-use
//injector.RegisterType<ExtractIncomingPrincipal, PrincipalExtractor>();
}
public void Dispose() {
injector.Dispose();
}
public object Build(Type typeToBuild) {
return injector.Resolve(typeToBuild);
}
public IContainer BuildChildContainer() {
return new ObjectBuilderAdapter(new DependencyInjectorBuilder());
}
public IEnumerable<object> BuildAll(Type typeToBuild) {
return injector.ResolveAll(typeToBuild);
}
public void Configure(Type component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void Configure<T>(Func<T> component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void ConfigureProperty(Type component, string property, object value) {
if (injector is AutofacDependencyInjector) {
((AutofacDependencyInjector)injector).ConfigureProperty(component, property, value);
} else {
Debug.WriteLine("Configuring {0} for property {1} but we don't handle this scenario.", component.Name, property);
}
}
public void RegisterSingleton(Type lookupType, object instance) {
injector.RegisterInstance(lookupType, instance);
}
public bool HasComponent(Type componentType) {
return injector.IsRegistered(componentType);
}
public void Release(object instance) { }
}
public static class Extensions {
public static Configure ObjectBuilderAdapter(this Configure config) {
ConfigureCommon.With(config, new ObjectBuilderAdapter(new DependencyInjectorBuilder()));
return config;
}
}
Note: When I use the INeedInitialization interface, I get the ComponentNotRegisteredException when it's looking for IStartableBus.
When you are trying to swap the built in container, then you need to implement IWantCustomInitialization in the same class that implements IConfigureThisEndpoint.
You can use your own container and register all your types in there and tell NSB to use that container.
For example:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public void Init()
{
var container = new ContainerBuilder().Build();
Configure.With()
.AutofacBuilder(container);
}
}

Resources