Mock Controller method with no Dependency Injection - c#

The controller has no dependency injection here is the code.
public class AccountingController : BaseApiController
{
[HttpGet]
    [Route("Accounting/Currency/{code}")]
    public HttpResponseMessage GetCurrencyCode(String code)
    {
       Log.Info($"GET Accounting/Currency/{code}"); //how to run this static method
       arguments.Add("code", code);
       return GetResult<Int16?, String>(code, m => new
Models.AccountsModels.AccountModel().CurrencySearchByCode(code)); //how to run this method
    }
}
The method mentioned inside it is Log.Info(static), arguments and GetResult the BaseApiController have
public abstract class BaseApiController : ApiController
{
public BaseApiController();
protected Dictionary<string, object> arguments { get; set; }
protected HttpResponseMessage GetResult<T, U>(U args, Func<U, T> doWork, long?
partialContentCount = null);
}
Now I want to understand that how can I mock a controller with various methods running as I tried this way.
[Fact]
public void GetCurrency_ActionExecutes_ReturnsHttpResponseMessage()
{
var controller = new AccountingController();
var data = controller.GetCurrencyCode(currency) as
HttpResponseMessage;
Assert.True(data != null);
}
It ran but failed on Log.Info and I suppose will not work on arguments and GetResult as well
'Could not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.'
This would run only on API but I want to directly access the controller and run these methods inside it.
I'm using xUnit but cannot find a way to run on these so called controller methods. I've read some place that MS Moles and Typemock can help but don't know how that can mock these internal methods of a controller.

You can do some hand-made workaround...
If you can modify and extend behaviors of the Log class you can try something like this:
public static class Log
{
private static ILogger instance { get; set; }
static Log()
{
bool isTesting = /* Find a way here to tell at runtime if you're
* testing or not.
* At very last option, for example, in your test's
* arrange-code, BEFORE any call to Log class,
* writes a txt file or whatever and read it
* here to determine if this is true or false.
* (obviously perform a proper cleanup)
* Use app configuration or a method that suits
* your architecture...
* * The key point here is that the Log static ctor
* must be able to know if it's testing time at
* runtime, since you can't pass variables to
* static ctors.
*/
if (isTesting)
{
instance = new LoggerStub();
}
instance = new Logger();
}
public static void Info(string message)
{
instance.Write("INFO", message);
}
public static void Warning(string message)
{
instance.Write("WARNING", message);
}
/* if you are not able to use the ctor-trick
* and you're allowed to do so, you can also perform a
* instance switch
*/
public static void InstanceSwitch(LoggerStub stub)
{
instance = stub;
}
}
public interface ILogger
{
void Write(string logLevel, string message);
}
internal class Logger : ILogger
{
public void Write(string logLevel, string message)
{
//writes, access file system,
//whatever
}
}
internal class LoggerStub : ILogger
{
public void Write(string logLevel, string message)
{
//do nothing
//or whatever you wish
}
}
About "arguments" and "GetResult()" you can work some hand-made tricks as well, (again assuming you can modify these classes):
public abstract class BaseApiController : ApiController
{
public BaseApiController();
protected Dictionary<string, object> arguments { get; set; }
/* virtual if it has body which you use in other subclasses
* abstract otherwise
*/
protected virtual HttpResponseMessage GetResult<T, U>(U args, Func<U, T> doWork, long?
partialContentCount = null);
}
public class AccountingController : BaseApiController
{
protected virtual Models Models { get; set; }
[HttpGet]
[Route("Accounting/Currency/{code}")]
public HttpResponseMessage GetCurrencyCode(string code)
{
Log.Info($"GET Accounting/Currency/{code}");
arguments.Add("code", code);
return GetResult<Int16?, string>(code, m =>
Models.AccountsModels.AccountModel().CurrencySearchByCode(code));
}
}
internal class AccountingControllerMock : AccountingController
{
protected override Models Models { get; set; }
/*
* Use this to set up Models
*/
public void ModelsSetUp( /*any parameters you need for models*/)
{
//set up Models
}
/*
* Or use ModelsStub if you want to be more explicit building
* a class in your test
*/
public void ModelsSetUp(ModelsStub models)
{
Models = models;
}
/*
* Use this to set up the dictionary
*/
public void ArgumentsSetup(string key, object value)
{
arguments.Add(key, value);
}
protected override HttpResponseMessage GetResult()
{
//return whatever you wish
}
}
internal class ModelsStub : Models
{
/* override things here in order to
* have control on what is going on
* */
}
(I'm used to put stubs and mocks directly in testing project(s) and/or in a test-api project which extend internal visibility to testing project(s), that's why are them marked as internal. It also helps to avoid that someone (not intentionaly using autocompletion maybe) uses these fake classes in production's code).
Then use ApplicationControllerMock to test the behavior of GetCurrencyCode unit.
They are somewhat hard books to digest but:
"Working effectively with legacy code" by Micheal Feather
"The art of unit testing" by Roy Osherove
definitely, both, worth the reading!

Related

Having some parameters Injected with DI and some assigned manually

In a .NET Core 3.1 console application I want a Class that would have some parameters in constructor injected but some that I could assign manually. For example something like that but with IConfiguration Injected:
static void Main() {
var myObj1 = new MyClass(1);
var myObj2 = new MyClass(2);
}
public class MyClass {
public MyClass(IConfiguraiton config, int myVal)
{
}
}
I tried this with Ninject:
static void Main()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Get<MyClass>();
}
public class MyClass
{
public MyClass(IConfiguraiton config)
{
}
}
public class Bindings : NinjectModule
{
public override void Load()
{
var configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();
Bind<IConfiguration>().ToMethod(ctx => SetupConfiguration()).InSingletonScope();
Bind<MyClass>().ToSelf().InTransientScope();
}
}
I managed to make simple dependency injection, but haven't had any success making injection with parameters.
I've read a lot of people suggesting that it's better to pass parameters into methods of the class rather than constructor, however in my situation this isn't an option in addition I'm a software engineering student, and would like to learn how to do this, since it might be useful in some situations.
This is a situation where the Ninject.Extensions.Factory is useful, as it is made exactly for this situation. It does pull in the Factory dependency in addition to Castle.Core, as it uses DynamicProxy under the hood (as a SE student, playing with this library is a good idea for using the interceptor pattern).
To use it, you define a Factory interface like so:
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
Note that the Create method returns MyClass, and the argument(s) to the Create method match exactly in type and name to the arguments you wish to provide. The argument type(s) you want injected must be registered with the kernel. Unfortunately, it is easy to make a mistake here - if you specify a parameter that does not exist in the factory interface it is ignored, but if you forget one it will throw an exception when called.
Next, register IMyClassFactory like this: Bind<IMyClassFactory>().ToFactory(); and remove your binding for MyClass. Then wherever you need to create an instance, inject IMyClassFactory and call Create: kernel.Get<IMyClassFactory>().Create(2)
You can achieve the same result without using Ninject.Extensions.Factory by writing and registering your own implementation of IMyClassFactory, essentially doing the same thing that the code the Factory extension ends up emitting. A full sample is below using both methods based on commenting in/out the registration (note the output if you add .InSingletonScope() to the registration of IConfiguraiton - both approaches respect the binding scopes of Ninject).
internal class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IConfiguraiton>().To<Configuraiton>();
kernel.Bind<IMyClassFactory>().ToFactory();
//kernel.Bind<IMyClassFactory>().To<NinjectMyClassFactory>().InSingletonScope();
var factory = kernel.Get<IMyClassFactory>();
var one = factory.Create(1);
var two = factory.Create(2);
}
}
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
public class NinjectMyClassFactory : IMyClassFactory
{
public NinjectMyClassFactory(IResolutionRoot resolutionRoot)
{
ResolutionRoot = resolutionRoot;
}
private IResolutionRoot ResolutionRoot { get; }
public MyClass Create(int myVal)
{
return ResolutionRoot.Get<MyClass>(new ConstructorArgument("myVal", myVal));
}
}
public class MyClass
{
public MyClass(IConfiguraiton config, int myVal)
{
Console.Out.WriteLine("Created MyClass({0},{1})", config.MyNum, myVal);
}
}
public interface IConfiguraiton { int MyNum { get; } }
public class Configuraiton : IConfiguraiton
{
static int CreateCount;
public Configuraiton()
{
MyNum = Interlocked.Increment(ref CreateCount);
}
public int MyNum { get; }
}

Is there a way to implement an adapter or interface without changing a class that uses it in this situation?

I'm trying to learn and understand interfaces, adapters, and dependency injection and how they can be used to achieve abstraction.
TLDR: How to change the way function\class uses the interface without changing said class\function's code?
I would also like it if you could point out errors in my thinking.
The Example:
Let's say I need to develop a logging mechanism (implement an ILogger interface) for some class (MoneyAdder) that I'm not allowed to modify. I also need to implement usage (please give me a correct term for this) of some other loggers via an adapter so we could choose the best way.
class MoneyAdder
{
private ILogger logger;
private Customer customer;
public MoneyAdder(ILogger logger, Customer customer)
{
this.logger = logger;
}
public void AddMoney(int amount)
{
logger.log("Doing work!");
customer.balance+=amount;
logger.log("I'm done!");
}
}
This is what I did at first:
public interface ILogger
{
void log(string str);
}
public class MyLogger : ILogger
{
public void log(string str)
{
Console.WriteLine($"LOG - {str}");
}
}
In this case, I have complete control over the interface definition, the class that implements it, and is able to use the log string that is given any way I want.
We know that OtherLogger requires a string and it's length to write a log. To use it I wrote an adapter like this:
public class OtherLogger
{
//We know it needs a string and its length for some reason.
public void log2(string str, int i);
}
public class OtherLoggerAdapter : ILogger
{
private OtherLogger ol = new OtherLogger();
public void log(string str)
{
ol.log2(str, str.Length);
}
}
This way I adapt the other dll to my interface. When the adapter is called I, in turn, call the different method name. I'm also able to provide an int it needs because it's computable from the input.
Now I need to add another logger that needs a log string and an assembly from which it was referenced. I'm able to provide it as well. It is not computable from the log string, but I'm able to give it any common information, like the environment variables or the program name because it is common for the program, MoneyAdder class, and StrangeLoggerAdapter.
public class StrangeLogger
{
public void logS(string str, System.Reflection.Assembly assembly);
}
public class StrangeLoggerAdapter : ILogger
{
private StrangeLogger sl = new StrangeLogger();
public void log(string str)
{
sl.logS(str, System.Reflection.Assembly.GetExecutingAssembly());
}
}
The final logger is an old mechanism that was used before. It was directly referenced and called inside MoneyAdder's other methods. (Tightly coupled, is this the correct term?). The logging method definition is as follows:
public class OldLogger
{
public void log(string str, string customerName);
}
It needs a customer name, but it is neither computable from the log string, nor it can be accessed from any adapter I can write. The only way to use it is to "inject" a customer name into a logger like this:
public interface ILogger
{
void log(string str);
void injectCustomer(string customerName);
}
And then to implement it in an adapter like this:
public class OldLoggerAdapter
{
private string customerName;
private OldLogger ol = new OldLogger();
public void injectCustomer(string customerName)
{
this.customerName = customerName;
}
public void log(string str)
{
ol.log(str, this.customerName);
}
}
However, to use the implementation I still need to modify (which I'm not allowed to do) either the MoneyAdder class or AddMoney method to use the injection function.
class MoneyAdder
{
private ILogger logger;
private Customer customer;
public MoneyAdder(ILogger logger, Customer customer)
{
this.logger = logger;
this.logger.injectCustomer(customer.Name);
}
public void AddMoney(int amount)
{
logger.log("Doing work!");
customer.balance+=amount;
logger.log("I'm done!");
}
}
The question:
To implement a logging function I can only use the information, that is either provided to the function via a method or can be computed from that information, or is global to the entire program.
There is no way to directly provide or inject information without modifying the calling function.
Or is there?
Is there a way, using some System\Reflexion\DI\IOC magic, to write something like:
Hey, MoneyAdder, It's an OldLogger that is currently used as ILogger. Whenever you call log(string str) you should actually call my method log(string str, string customerName). I know for sure you have a private property Customer that has a Customer.Name, use that in my log method as a "customerName".

Inherit static methods that call their derived parent's methods

I'm trying to write a logging class that would work like this:
Log.Info("Something happened");
Log.Error("Something else happened");
Log.Debug("Yet another thing happened!");
It should be accessible from every part of the namespace and quick to write, so I thought it'd be best to make it static. That way one can avoid having to create an object just to log a message.
At this point it is sort of like Console.WriteLine();
However, I wanted it also to be able to have two different modes: LogToConsole and LogToFile.
Thus the following syntax would be the most convenient:
LogConsole.Info("This will display in the console");
LogFile.Debug("This will be saved to a file");
LogAll.Error("This will be saved to a file AND displayed in a console");
However, I realized that there could be an large amount of "modes" multiplied by a very large amount of "logtypes".
How could I do this efficiently, in a way that I only have to write each logtype method once and depending on the derived class that calls the method, action a happens or action b happens?
Ideally I would like to define all methods once, and then create the classes that inherit them. But, since they are static methods their behavior is always the same. I can't tell them: "Find out what your superclass is and execute that class' SaveLog() method".
I realize that this would all be very very easy with abstract classes, but then I'd have to create objects.
Is there any way I could do this in C#?
Thanks!
Like Boo, would also recommend a logger like log4net.
If you do want to write it yourself, I would recommend against static methods as they would inhibit your ability to test the classes / methods that call it. Instead, inject your ILogger interface to all classes that might need logging. Then separate the "mode" from the target, so you can inject a list of targets to your logger.
public interface ILogTarget
{
void Save(string message);
}
public class LogToFile : ILogTarget
{
public void Save(string message)
{
//
}
}
public class LogToConsole : ILogTarget
{
public void Save(string message)
{
//
}
}
public interface ILogger
{
void Debug(string message);
}
public class Logger : ILogger
{
private readonly List<ILogTarget> _targets;
private static Logger _logger;
public Logger(List<ILogTarget> targets)
{
_targets = targets;
}
public void Debug(string message)
{
foreach (var target in _targets)
target.Save($"Debug: {message}");
}
}
public class TheClassThatMakesTheCall
{
private readonly ILogger _logger;
public TheClassThatMakesTheCall(ILogger logger)
{
_logger = logger;
}
public void AMethod()
{
_logger.Debug("some message");
}
}
//In your IoC, register Logger as a type of ILogger, and pass in the targets that you want
//If your target vary per situation, you'll need a ILogTarget factory that returns a different list of loggers based on the situation
You cannot inherit from static classes. But you can get away with making only the functions static. don't make the classes as static. Just make the functions as static, then you can use the "new" keyword in the derived class. It would be something like this
// IF this is your base class
public class Log
{
public static bool Info(string Message)
{
Console.WriteLine(Message + " From Log");
return true;
}
public static bool Success(string Message)
{
return true;
}
public static bool Error(string Message)
{
return true;
}
}
//Then this can be your derived class
public class LogFile : Log
{
public static new bool Info(string Message)
{
Console.WriteLine(Message + " From LogFile");
return true;
}
public static new bool Success(string Message)
{
return true;
}
public static new bool Error(string Message)
{
return true;
}
}
Hope this helps.

How to model this scenario using OOP? (inheritance issue)

I have a lot of different engines that implement different algorithms. All of them implement the same interface but have different Configuration methods. Most of them are configured without parameters, some of them with one integer and even less with two integers. There is a small probability that in the future we will have with three or even four integers.
I need to create a Engine controller that decides when it has to start or stop the engine as this is common for all of them. The options I thought are the following:
Create an unique interface with as much parameters as the biggest Configure method available and ignore the not needed ones at the engines. This way I'll have just only one EngineController.
Create an Interface for each of the different configure methods and create a EngineController for each one of the different interfaces (but this will make me create a lot of classes that only differ on the number of parameters and will require 2 new classes each time a new parameter is added to an engine.
...
I really don't feel comfortable with any of the two solutions as passing unneeded parameters looks 'ugly' and due to the high number of classes generated with the second option (that only have very minor differences).
Any design or pattern that avoids this problem?
EDIT (Thanks for the answers, this edit answers all of them and clarifies the question):
Just to give an example, these are the engines.
abstract class EngineBase
{
public void Start() {...}
public void Stop() {...}
}
class EngineOne : EngineBase
{
public void Configure(int parameter1) {...};
}
class EngineTwo : EngineBase
{
public void Configure(int parameter1, int parameter2) {...};
}
class EngineThree : EngineBase
{
public void Configure(int parameter1, int parameter2, int parameter3) {...};
}
As all the engines have the same logic to decide when to start or end I want to create a new class that handles them, called EngineController. The controller will call the Configure, the Start and the Stop when needed:
class EngineController
{
EngineBase _engine; ??? or what?
void SuperviseEngine() { ... _engine.Configure(x,x,...) ... _engine.Start() ...
}
The first idea I has is to add to the EngineBase class the next method:
abstract class EngineBase
{
public void Start() {...}
public void Stop() {...}
public void Configure(int parameter1, int parameter2, int parameter3) {...}
}
class EngineController
{
EngineBase _engine;
void SuperviseEngine() { ... _engine.Configure(x,y,z) ... _engine.Start() ...
}
and ignore the unneeded parameters but I don't like the idea. Then I thought on doing the following:
interface I1ParameterConfigurable
{
public void Configure(int parameter1) {...};
}
interface I2ParameterConfigurable
{
public void Configure(int parameter1, int parameter2) {...};
}
interface I3ParameterConfigurable
{
public void Configure(int parameter1, int parameter2, int parameter3) {...};
}
and then create 3 different controllers for each kind of engine:
class EngineController1Parameter
{
EngineBase _engine;
I1ParameterConfigurable _configurableEngine = _engine as I1ParameterConfigurable;
void SuperviseEngine() { ... _configurableEngine .Configure(x) ... _engine.Start()
}
class EngineController2Parameter
{
EngineBase _engine;
I2ParameterConfigurable _configurableEngine = _engine as I2ParameterConfigurable;
void SuperviseEngine() { ... _configurableEngine .Configure(x, y) ... _engine.Start()
}
You get the idea, but I feel that this will create a lot of interfaces / classes when maybe there is way to avoid this.
Thanks to your answers I have a third option that is similar to the 1st one but using an array (or IEnumerable or whatever) to pass a undefined number of parameters. The idea is not bad but then I'll lose the parameter names. But maybe it's the best option until now.
Will that help you.
interface IEngine
{
void startEngine(params int[] engineParam);
}
Maybe I don't fully understand but I think you want something like this:
public interface IEngineController //I dont see a need to expose the enigine here in this pseudo code
{
void Start();
IConfiguration Config { get; }
}
public interface IEngine
{
void Start();
}
public interface IConfiguration
{
bool IsOkToStart { get; }
}
public class Configuration : IConfiguration
{
public Configuration(List<IConfigurationParameter> configurationParameters)
{
ConfigurationParameters = configurationParameters;
}
public bool IsOkToStart
{
get { return ConfigurationParameters.All(cfg=>cfg.IsOkToStart); }
}
protected List<IConfigurationParameter> ConfigurationParameters { get; private set; }
}
public interface IConfigurationParameter
{
bool IsOkToStart { get; }
}
public interface IMaxTemp : IConfigurationParameter
{
double MaxTemp { get; }
}
public interface ISafetyParameter : IConfigurationParameter
{
ISafetyCondition SafetyCondition { get; }
}
This got a little long, I omitted Stop() for brevity. The idea is:
The controller has an IEngine (not exposed in the interface) and an IConfig
IEngine has the Start() method.
A Configuration is a list of IConfigparameters that has a bool is ok to start (if all parameters are ok).
Each parameter has an IsOkToStart that is calculated depending on some condition
Maybe this provides flexibility for you? Combine the parameters you need and possibly add ned parameters in the future. I believe it is a good thing that the interfaces are extremely small and cohesive. Maybe even split them into IStartParameter and IStopParameter and just combine to the desired config?
I would model it similar to this:
public interface IEngine1 {
}
public interface IEngine1Config {
int Param1 {get;}
}
public Engine1 : IEngine1 {
IEngine1Config _config;
public Engine1(IEngine1Config config) {
_config = config;
}
}
You could then optionally choose to have one class implementing the different engine configurations:
class AllEnginesConfig : IEngine1Config, IEngine2Config {
int Param1 {get;set;}
// ... etc
}
(of course, it may be better in your situation to implement the configs in separate classes also)
If you have a lot of engines, I would use an IoC container to register all the different types, and let it wire up all the dependencies.
container.Register<IEngine1, Engine1>();
var theOneAndOnlyConfig = new AllEnginesConfig() {}; // properly initialized, of course
container.RegisterInstance<IEngine1Config>(theOneAndOnlyConfig);
container.RegisterInstance<IEngine2Config>(theOneAndOnlyConfig);
// ...
Then, to instantiate an engine, you simply use the container:
container.Get<IEngine1>();
IOC containers to invoke a engine you require or bunch of engines you require and inject them at run time and you can use them in combination with optional parameters while invoking containers. I have seen usage of Optional parameters in many attributes of .NET FW. or use an list of object parameter to get all inputs and when called can parse the list and decide which engine it was intended to invoke. None of them will be hard to grasp and use

Virtual Extension Methods?

I have a class that gets used in a client application and in a server application.
In the server application, I add some functionality to the class trough extension methods. Works great. Now I want a bit more:
My class (B) inherits from another class (A).
I'd like to attach a virtual function to A (let's say Execute() ), and then implement that function in B. But only in the server. The Execute() method would need to do stuff that is only possible to do on the server, using types that only the server knows about.
There are many types that inherit from A just like B does, and I'd like to implement Execute() for each of them.
I was hoping I could add a virtual extension method to A, but that idea doesn't seem to fly. I'm looking for the most elegant way to solve this problem, with or without extension methods.
No, there aren't such things as virtual extension methods. You could use overloading, but that doesn't support polymorphism. It sounds like you might want to look at something like dependency injection (etc) to have different code (dependencies) added in different environments - and use it in regular virtual methods:
class B {
public B(ISomeUtility util) {
// store util
}
public override void Execute() {
if(util != null) util.Foo();
}
}
Then use a DI framework to provide a server-specific ISomeUtility implementation to B at runtime. You can do the same thing with a central static registry (IOC, but no DI):
override void Execute() {
ISomeUtility util = Registry.Get<ISomeUtility>();
if(util != null) util.Foo();
}
(where you'd need to write Registry etc; plus on the server, register the ISomeUtility implementation)
You can use the new dynamic type functionality to avoid having to build a registry of types to methods:
using System;
using System.Collections.Generic;
using System.Linq;
using visitor.Extension;
namespace visitor
{
namespace Extension
{
static class Extension
{
public static void RunVisitor(this IThing thing, IThingOperation thingOperation)
{
thingOperation.Visit((dynamic)thing);
}
public static ITransformedThing GetTransformedThing(this IThing thing, int arg)
{
var x = new GetTransformedThing {Arg = arg};
thing.RunVisitor(x);
return x.Result;
}
}
}
interface IThingOperation
{
void Visit(IThing iThing);
void Visit(AThing aThing);
void Visit(BThing bThing);
void Visit(CThing cThing);
void Visit(DThing dThing);
}
interface ITransformedThing { }
class ATransformedThing : ITransformedThing { public ATransformedThing(AThing aThing, int arg) { } }
class BTransformedThing : ITransformedThing { public BTransformedThing(BThing bThing, int arg) { } }
class CTransformedThing : ITransformedThing { public CTransformedThing(CThing cThing, int arg) { } }
class DTransformedThing : ITransformedThing { public DTransformedThing(DThing dThing, int arg) { } }
class GetTransformedThing : IThingOperation
{
public int Arg { get; set; }
public ITransformedThing Result { get; private set; }
public void Visit(IThing iThing) { Result = null; }
public void Visit(AThing aThing) { Result = new ATransformedThing(aThing, Arg); }
public void Visit(BThing bThing) { Result = new BTransformedThing(bThing, Arg); }
public void Visit(CThing cThing) { Result = new CTransformedThing(cThing, Arg); }
public void Visit(DThing dThing) { Result = new DTransformedThing(dThing, Arg); }
}
interface IThing {}
class Thing : IThing {}
class AThing : Thing {}
class BThing : Thing {}
class CThing : Thing {}
class DThing : Thing {}
class EThing : Thing { }
class Program
{
static void Main(string[] args)
{
var things = new List<IThing> { new AThing(), new BThing(), new CThing(), new DThing(), new EThing() };
var transformedThings = things.Select(thing => thing.GetTransformedThing(4)).Where(transformedThing => transformedThing != null).ToList();
foreach (var transformedThing in transformedThings)
{
Console.WriteLine(transformedThing.GetType().ToString());
}
}
}
}
I would suggest something like the following. This code could be improved by adding support for detecting intermediate class hierarchy types that don't have a dispatch mapping and calling the nearest dispatch method based on the runtime hierarchy. It could also be improved by using reflection to detect overload of ExecuteInteral() and adding them automatically to the dispatch map.
using System;
using System.Collections.Generic;
namespace LanguageTests2
{
public class A { }
public class B : A {}
public class C : B {}
public static class VirtualExtensionMethods
{
private static readonly IDictionary<Type,Action<A>> _dispatchMap
= new Dictionary<Type, Action<A>>();
static VirtualExtensionMethods()
{
_dispatchMap[typeof(A)] = x => ExecuteInternal( (A)x );
_dispatchMap[typeof(B)] = x => ExecuteInternal( (B)x );
_dispatchMap[typeof(C)] = x => ExecuteInternal( (C)x );
}
public static void Execute( this A instance )
{
_dispatchMap[instance.GetType()]( instance );
}
private static void ExecuteInternal( A instance )
{
Console.WriteLine("\nCalled ToString() on: " + instance);
}
private static void ExecuteInternal(B instance)
{
Console.WriteLine( "\nCalled ToString() on: " + instance );
}
private static void ExecuteInternal(C instance)
{
Console.WriteLine("\nCalled ToString() on: " + instance);
}
}
public class VirtualExtensionsTest
{
public static void Main()
{
var instanceA = new A();
var instanceB = new B();
var instanceC = new C();
instanceA.Execute();
instanceB.Execute();
instanceC.Execute();
}
}
}
Virtual implies inheritance in a OOP way and extension methods are "just" static methods that through a bit a syntactic sugar the compiler allows you to pretend to call on an instance of the type of its first parameter. So no, virtual extension methods are out of the question.
Check out the answer by Marc Gravell for a possible solution to your problem.
You can implement a service register. Example (server side):
static IDictionary<Type, IService> serviceRegister;
public void ServerMethod(IBusinessType object)
{
serviceRegister[obect.GetType()].Execute(object);
}
What you need are rather services in your server, which implement server side functionality, instead of extension methods. I wouldn't put to much logic into extension methods.
Let me check: you have a class hierarchy inheriting from A, presumably structured according to your business domain. Then you want to add behaviours depending on where the classes execute. So far you've used extension methods, but now you find you cannot get them to vary with your class hierarchy. What kinds of behaviours are you attaching at the server?
If it's stuff like transaction management and security, policies implemented through dependency injection à la Marc's suggestion should work well. You could also consider implementing the Strategy pattern through delegates and lambdas, for a more limited version of DI. However, what's not clear is how client code currently uses your classes and their extension methods on the server. How dependent are other classes on how you add the server-side functionality? Are they server-side only classes that currently expect to find the extension methods?
In any case, it sounds like you're going to need a careful testability design and testing strategy since you are introducing variation along two simultaneous dimensions (inheritance hierarchy, execution environment). You are using unit testing, I trust? Check that whatever solution you choose (e.g. DI through configuration) interacts well with testing and mocking.

Categories

Resources