Does Microsoft Fakes support abstract methods on a shim? - c#

I have a class setup in the following manner:
public abstract FooClass {
public FooClass() {
// init stuff;
}
public void RandomMethod() {
// do stuff;
}
public abstract WhatIWantToShim();
}
What I want to do is set the WhatIWantToShim on the ShimFooClass like so:
ShimFooClass.AllInstances.WhatIWantToShim = () => Boo();
I can set RandomMethod just fine,
ShimFooClass.AllInstances.RandomMethod = () => CalculatePi();
However, it appears that the generated ShimFooClass does not create the WhatIWantToShim property on the AllInstances property of the ShimFooClass.
I've looked at http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basics but I don't see anything there about abstract methods. The only thing I see referenced that is not supported is finalizers. Anybody know what is going on here and if this scenario is supported?

Ahhh....bummer
Interfaces and abstract methods. Stubs provide implementations of interfaces and abstract methods that can be used in testing. Shims can’t instrument interfaces and abstract methods, because they don’t have method bodies.
http://msdn.microsoft.com/en-us/library/hh549175(v=vs.110).aspx
Update: what can be done though is stubbing the shim.
using (ShimsContext.Create())
{
bool wasAbstractMethodCalled = false;
var targetStub = new StubFooClass()
{
WhatIWantToShim01 = () => wasAbstractMethodCalled = true
};
var targetShim = new ShimFooClass(targetStub);
targetShim.AllInstances.RandomMethod = () => CalculatePi();
FooClass target = targetShim.Instance;
target.WhatIWantToShim();
Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}
Since the shim cannot handle detouring the WhatIWantToShim method and the stub can, just create a new instance of the stub class and set the detour handler for the abstract method. (Note: the 01 tagged on the end of WhatIWantToShim was added automatically for me when the Fakes were generated in my actual code).
Then just pass the instantiated stub to the constructor of the shim class and shim away as needed.

I'm replying here because I'm quite sure the other answer did not answer the question, and so that future searches return useful information.
Firstly, you cannot shim interfaces. An abstract method is equivalent to an interface. Furthermore, there is no reason to.
{
bool wasAbstractMethodCalled = false;
var targetStub = new StubFooClass()
{
WhatIWantToShim01 = () => wasAbstractMethodCalled = true
};
ShimFooClass.AllInstances.RandomMethod = #class => targetStub.CalculatePi();
targetStub.WhatIWantToShim();
Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}
The above is a simplified version of a previous answer, and will simply call the action you just assigned. This is probably not your intent.
Remember WHY you shim. You shim when you want to avoid the effects of a method call within a method you are testing. The abstract method can have no body, and therefore cannot affect anything. The only time this would be useful is in a child class, where the shim would be available to you in the first place.
The only situation in which you might have an issue is if a third class is secretly holding an instance of the abstract class and instantiating it with the child class. You can't fake that. It is, however, terrible design; the instance should be coming from some method (which you can shim) or passed in (Because DI is a good thing!) or else the abstraction is worthless, and you may as well have the instance declared to be the child type, since you aren't using the abstraction in any way.

Related

C# simplify and perhaps generalize my object cloning method

I've written a method:
class CopyableFloatCommand : FloatCommand
{
public CopyableFloatCommand DeepCopy(LocationHeaderDTO locHeader, string commandId,
List<FloatProductDetailsDTO> recountProuducts)
{
var newCommand = (CopyableFloatCommand)MemberwiseClone();
newCommand.Location = locHeader ?? newCommand.Location;
newCommand.CommandId = commandId ?? newCommand.CommandId;
newCommand.RecountProducts = recountProuducts ?? newCommand.RecountProducts;
return newCommand;
}
}
And am then calling it via:
_tCheckinCommand = _pTCommand.DeepCopy(stagingLocHeadDto, SCICommand,
new List<FloatProductDetailsDTO>(_pTCommand.MoveProducts));
In order to deepcopy an object of type FloatCommand.
As the MemberwiseClone() is a protected method, it's got to be called the way you see above - one cannot parse in a FloatCommand type in the method parameter and call it via fc.MemberwiseClone(), for example. As my method ought to work on a FloatCommand type, I've created a new nested class CopyableFloatCommand which inherits from FloatCommand. DeepCopy method then shallow clones the FloatCommand, casts to the child type and changes some properties as/when needed.
Creating a new class specifically for this purpose seems a bit clunky and I didnt' see a more obvious way of writing it at the time. In terms of lines-of-code, would there be a simpler way of employing a deepcopy such as the above? What about if another class, UserCommand, attempted to deepcopy a User object? UserComand would be a sibling to FloatCommand such that they both inherit from Command. The method would have different parameters parsed for the different types (although I can just remove the parameters altogether and use the instance variables if need be) as the different sub-types have slightly different properties.
In light of this is there a more generic method of writing the DeepCopy method, to be available for access for all the Command types in order to avoid some code duplication, given the above constraints?
Thanks!
I think you're suspecting that the responsibility of cloning the object and mutate its state after it is cloned should be separated - since you're facing with the similar task again (i mean UserCommand).
I would do the following in this situation:
Create a mutation interface:
public interface ICopyCommandMutation
{
void Mutate(Command target);
}
For the sake of extensability i would create the default muate implementation:
public class NoMutation : ICopyCommandMutation
{
public void Mutate(Command target) {}
}
Create the CopyableCommand class and move the DeepCopy() method there (you should also inherit FloatCommand from CopyableCommand):
public CopyableCommand : Command
{
public CopyableCommand DeepCopy(ICopyCommandMutation commandMutation = null)
{
var newCommand = (CopyableCommand)MemberwiseClone();
if (commandMutation == null) commandMutation = new NoMutation();
commandMutation.Mutate(newCommand);
return newCommand;
}
}
Now all the CopyableCommand inheritors can be copied with 'mutations' - you just need to implement the class. For example the FloatCommand 'mutations' from your question:
public class ChangeLocationRecountProducts : ICopyCommandMutation
{
// these fields should be initialized some way (constructor or getter/setters - you decide
LocationHeaderDTO locHeader;
string commandId;
List<FloatProductDetailsDTO> recountProducts;
public void Mutate(Command floatCommand)
{
var fc = floatCommand as FloatCommand;
if (fc == null) { /* handle problems here */ }
fc.Location = locHeader ?? fc.Location;
fc.CommandId = commandId ?? fc.CommandId;
fc.RecountProducts = recountProuducts ?? fc.RecountProducts;
}
}
Here is the usage:
var clrp = new ChangeLocationRecountProducts();
// ... setting up clrp
_tCheckinCommand = _pTCommand.DeepCopy(clrp);
Now if you need to 'mutate' the UserCommand - you can do the separate mutation class for it and keep the mutation logic there. The ability to make different mutations in different sutations (just by defining the separate mutation classes) comes for free.
The only problem i can see here - is that you probably cannot create CopyableCommand and inherit other commands from it (3rd party library?). The solution would be to use Castle dynamic proxy.
I haven't used the Automapper but i suspect that it is doing something similar.
The solution is not 'lines-of-code optimal' - but you would benefit from it if you have to mutate large number of command classes when copying instances.

How to use generics to handle type-specific configurations in an Action<IBuilder<T>>?

I am trying to implement a complex builder to help my testing context. To do that I refactored my code to have a method :
public TestContext Add<T>(Action<IBuilder<T>> configurator) where T : class, new()
{
IBuilder<T> builder = CreateBuilderOf<T>();
configurator(builder);
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
The problem arises when I need to specify the configuration when calling the method :
TestContext.Instance.Add<Person>(personBuilder => ((PersonBuilder)personBuilder).Name("SMITH"));
I need to be able to use type specific methods in the configurator, which are implemented by the concrete builders, such as :
public PersonBuilder : IBuilder<Person>
{
private Person Item;
public PersonBuilder() { Item = new Person(); }
public Name(string mame) { Item.Name = name; }
public Person GetItem() { return Item; }
}
Apparently, passing an Action<PersonBuilder> as an Action<IBuilder<Person>> is not allowed, even though PersonBuilder implements IBuilder<Person>, hence the cast.
I would very much like to either :
Need not to cast inside the lambda but rather at the start of it, e.g.
(PersonBuilder personBuilder) => personBuilder.Name("SMITH"), but that boils down to being an instance of Action<PersonBuilder> and therefore is equally invalid;
Use a function such as BuildSimplePerson(PersonBuilder builder) in Add's argument : Add<Person>(BuildSimplePerson)
I think I can do a type casting through two BuildSimplePersons implementations such as :
private void BuildSimplePerson(IBuilder<Person> builder)
{
BuildSimplePerson(builder as PersonBuilder);
}
private void BuildSimplePerson(PersonBuilder builder)
{
builder.Name("SMITH");
}
But that is not really an elegant solution.
I also realize passing Action<PersonBuilder> as an Action<IBuilder<Person>> is incorrect because we don't know if the argument to that function will truly be a PersonBuilder or any other implementation of IBuilder<Person>.
How can I do better ?
As my comment already states, the problem is that your current code assumes that CreateBuilderOf<T> returns a PersonBuilder but it could actually return anything that implements IBuilder<Person> in which case your cast would fail.
Your code looks like it is generic, but in fact, it is not. You always want to work on the concrete class (PersonBuilder) and not on the general interface IBuilder<Person>.
My understanding is, that you want one generic Add<T> method to avoid having to repeat that code inside it for each type.
Here is my approach:
public TestContext Add<T>(IBuilder<T> builder) where T : class, new()
{
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
You would call it like this:
TestContext.Instance.Add<Person>(CreatePersonBuilder().Name("SMITH"));
Obviously, you would need to have a CreateXBuilder method for each type that you want to be able to add. However, I think you already have this at least implicitly, because I would assume that your CreateBuilderOf<T> method is one huge switch statement anyway.
If you don't want to create such methods, another approach to get the builder would be a generic method like so:
CreateBuilder<PersonBuilder>()
But really, this is actually nothing more than a new PersonBuilder(), so you actually could simply go with
TestContext.Instance.Add<Person>(new PersonBuilder().Name("SMITH"));
The Configure method would be very similar:
TestContext.Instance.Configure<Person>(id, p => new PersonBuilder(p).Name("SMITH"));
This would pass the ID, which the Configure method would use to look up the object, which in turn is passed to the callback. So the second parameter of Configure would not be a Action<IBuilder<T>> but an Action<T>.
This approach has another advantage over your existing code:
Your existing code assumes not just that PersonBuilder will be the implementation used for IBuilder<Person>. No, your code also assumes that it has a constructor without parameters and one which takes a Person. These assumptions are impossible for the compiler to verify.
With the code I showed above, a builder implementation could take additional parameters without problems and the compiler would verify that everything is alright.

How to forward to another object when using .NET Moq?

Given an object, I would like to create a mock that implements the interface of the object and mocks one method, but forwards the rest of the methods to the real object, not the base class.
For example:
ISqlUtil sqlUtil = GetTheRealSqlUtilObjectSomehow(...);
var mock = new Mock<ISqlUtil>();
mock.Setup(o => o.SpecialMethodToBeMocked(...)).Returns<...>(...)
// Here I would like to delegate the rest of the methods to the real sqlUtil object. How ?
So, in the example I want to mock just ISqlUtil.SpecialMethodToBeMocked and forward the rest of methods/properties to the existing instance sqlUtil.
Is it possible in Moq.NET ?
EDIT 1
It should work for generic methods as well.
You can't do this with Moq out of the box. However, I think you can achieve basically what you want if you go down to the next layer and use Castle DynamicProxy directly (which is what's underneath Moq).
So, given the following base code to simulate your issue (essentially, an interface, a concrete implementation and a factory because the concrete is hard to make/setup):
public interface ISqlUtil {
T SomeGenericMethod<T>(T args);
int SomeMethodToIntercept();
}
public class ConcreteSqlUtil : ISqlUtil {
public T SomeGenericMethod<T>(T args){
return args;
}
public int SomeMethodToIntercept() {
return 42;
}
}
public class SqlUtilFactory {
public static ISqlUtil CreateSqlUtil() {
var rVal = new ConcreteSqlUtil();
// Some Complex setup
return rVal;
}
}
You can then have the following test:
public void TestCanInterceptMethods() {
// Create a concrete instance, using the factory
var coreInstance = SqlUtilFactory.CreateSqlUtil();
// Test that the concrete instance works
Assert.AreEqual(42, coreInstance.SomeMethodToIntercept());
Assert.AreEqual(40, coreInstance.SomeGenericMethod(40));
// Create a proxy generator (you'll probably want to put this
// somewhere static so that it's caching works if you use it)
var generator = new Castle.DynamicProxy.ProxyGenerator();
// Use the proxy to generate a new class that implements ISqlUtil
// Note the concrete instance is passed into the construction
// As is an instance of MethodInterceptor (see below)
var proxy = generator.CreateInterfaceProxyWithTarget<ISqlUtil>(coreInstance,
new MethodInterceptor<int>("SomeMethodToIntercept", 33));
// Check that calling via the proxy still delegates to existing
// generic method
Assert.AreEqual(45, proxy.SomeGenericMethod(45));
// Check that calling via the proxy returns the result we've specified
// for our intercepted method
Assert.AreEqual(33, proxy.SomeMethodToIntercept());
}
The method interceptor looks like this:
public class MethodInterceptor<T> : Castle.DynamicProxy.IInterceptor {
private T _returns;
private string _methodName;
public MethodInterceptor(string methodName, T returns) {
_returns = returns;
_methodName = methodName;
}
public void Intercept(IInvocation invocation) {
if (invocation.Method.Name == _methodName) {
invocation.ReturnValue = _returns;
}
else {
invocation.Proceed();
}
}
}
Essentially, the interceptor checks if the method being called matches the one you're interested in and if so, returns the stored return value. Otherwise, it calls Proceed, which delegates the method call onto the concrete object supplied when the proxy was created.
The example code uses strings rather than lambdas to specify the method to intercept, obviously this could be changed (exercise for the reader). Also, this isn't using Moq, so you lose the Setup, Returns and Verify elements, which are replaced by the Interceptor, so this may be too far away from what you're after to be useful, however depending what your code really looks like it may be a viable alternative approach.
If you're unable to mock the class and delegate calls to the base by default, then you'll have to manually wire up the delegation to your separate instance.
var util = GetSqlUtil();
var mockUtil = new Mock<ISqlUtil>(MockBehavior.Strict);
mockUtil.Setup(x => x.SomeCall(...)).Returns<...>(args => util.SomeCall(args));
Having been successful with tricking Moq into creating a proxy for given class instance in my other SO answer here, I thought it would be easy to tweak the solution for your case of a given interface implementation.
No way
If you think of, it it makes sense: interface has no implementateion. And since Moq is aware mocked type is an interface - it does not even try to call the underlying proxy. That's it, end of story.
For those who don't give up easily
spoiler: still no luck
Looking at the library source code, I had a theory that it might be possible to force the correct execution path:
if (mock.TargetType.IsInterface) // !!! needs to be true here
{
// !!! we end up here and proceed to `DefaultValueProvider`
}
else
{
Debug.Assert(mock.TargetType.IsClass); // !!! needs to pass here
Debug.Assert(mock.ImplementsInterface(declaringType)); // !!! needs to pass here
// Case 2: Explicitly implemented interface method of a class proxy.
......
for that we could fulfill two conditions:
mock.TargetType should be a target class instance type
this.InheritedInterfaces should contain our interface
the second one is easy enough to build:
private void AddInheritedInterfaces(T targetInstance)
{
var moqAssembly = Assembly.Load(nameof(Moq));
var mockType = moqAssembly.GetType("Moq.Mock`1");
var concreteType = mockType.MakeGenericType(typeof(T));
var fi = concreteType.GetField("inheritedInterfaces", BindingFlags.NonPublic | BindingFlags.Static);
var t = targetInstance.GetType()
.GetInterfaces()
.ToArray();
fi.SetValue(null, t);
}
but as far as I'm aware, overriding an expression-bodied property marked internal (which Mock<>.TargetType is) is impossible without Reflection.Emit artillery, where it will likely become infeasible due to amonunt of overriding and subclassing required - you might be better off just forking Moq and patching the source code in this case (or submitting a PR maybe?).
What can be done
It should be possible to generate Setup LINQ expressions that automatically call through to your respective instance implementations:
//something along these lines, but this is basically sudocode
ISqlUtil sqlUtil = GetTheRealSqlUtilObjectSomehow(...);
var mock = new Mock<ISqlUtil>();
foreach(var methodInfo in typeof(ISqlUtil).GetMembers())
{ mock.Setup(Expression.Member(methodInfo)).Returns(Expression.Lambda(Expression.Call(methodInfo)).Compile()())
}
But given how much effort it is to account for everything properly, that again is probably not very feasible.
There is a workaround to do it, by using the method by #timur described in this answer.
While this method doesn't work directly on interfaces as described by his answer in the current thread, but it is indeed possible to do it via a generic factory method.
NOTE: The resulting Moq object will NOT be a true subclass rather it is a wrapped object and therefore only public virtual methods will be forwarded to the object (unlike a typical Moq which the base is automatically called for non public or non virtual methods/properties).
The factory mode would look like this:
static MyMock<T> CreateMock<T>(T target) where T : class, ISqlUtil
{
var superMock = new MyMock<T>(target); // now we can pass instances!
superMock.CallBase = true;
superMock.Setup(o => o.SpecialMethodToBeMocked(...)).Returns<...>(...);
return superMock;
}
And you use it like this:
var mockFunc = typeof(this).GetMethod("CreateMock").MakeGenericMethod(sqlUtil.GetType());
var superMock = mockFunc.Invoke(null, new object[] {sqlUtil}) as Mock;
While the implementation of MyMock will be based on the one described in this answer (but I am simplifying it a bit).
public class MyMock<T> : Mock<T>, IDisposable where T : class
{
public MyMock(T targetInstance)
{
var moqAssembly = typeof(Mock).Assembly;
var proxyFactoryType = moqAssembly.GetType("Moq.ProxyFactory");
var castleProxyFactoryInstance = proxyFactoryType.GetProperty("Instance").GetValue(null);
var castleProxyFactoryType = moqAssembly.GetType("Moq.CastleProxyFactory");
var generatorFieldInfo = castleProxyFactoryType.GetField("generator", BindingFlags.NonPublic | BindingFlags.Instance);
generatorFieldInfo.SetValue(castleProxyFactoryInstance, new MyProxyGenerator(targetInstance));
}
}
class MyProxyGenerator : ProxyGenerator
{
object _target;
public MyProxyGenerator(object target) {
_target = target;
}
// this method is 90% taken from the library source. I only had to tweak two lines (see below)
public override object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
{
if (_target is not null) return CreateClassProxyWithTarget(classToProxy, additionalInterfacesToProxy, _target, options, constructorArguments, interceptors);
return base.CreateClassProxy(classToProxy, additionalInterfacesToProxy, options, constructorArguments, interceptors);
}

Refactoring code that uses new operator to be more testable

I have the following code and am trying to unit test it:
public override IRenderable GetRenderable()
{
var val = SomeCalculationUsingClassMemberVariables();
return new EquationRenderable(val);
}
It seems like I want to use a factory here so I can separate the creation of the IRenderable from this class. The problem is that I have many of these classes that create different IRenderables that are constructed in different ways, so I would need to implement a new factory method for each one. What is the best way to solve this problem?
Good question.
First of all, feeling tempted to use AbstractFactories everywhere smells a bit as DI container is not used the "right" way or design could be improved.
But sometimes I've also come across this problem. I see following:
using AbstractFactory/Factory and Inject it. For C# you have to advantage that you can pass delegates, acting as interface for the creation of instance.
'new' is OK, simply test the output of 'new'.
Stub the call of 'new' inside extracted method (hacky!!)
Injection got mentioned already so I won't repeat. I am more into Java so please excuse some syntax errors.
Test the output of 'new'
I often use this, if the 'new' created instances are domain-objects and not services. Because it is returned directly in method I can test the direct output with my test.
Prod-Code:
...
public override IRenderable GetRenderable()
{
var val = SomeCalculationUsingClassMemberVariables();
return new EquationRenderable(val);
}
Test Case:
...
[Test]
public void test_new()
{
SUT sut = ...;
IRenderable r = sut.GetRenderable();
assertTrue(r instanceof EquationRenderable);
}
Stub the call of 'new' itself
Testing direct output from above is only possible if you somehow get it as return value. Things get more complicated if the "sideeffect" of your code are indirect outputs, which you can't sense directly by the return value. If so I often extract-method of the new-creation and then have it under control in my test. This is yucky and I more use it to go safe with my test and start more refactoring later (DI and factories). I sometimes do this in legacy code where services are created with 'new' directly and refactoring to DI is too risky without tests.
Prod-Code:
...
public override IRenderable GetRenderable()
{
var val = SomeCalculationUsingClassMemberVariables();
return createEquationRenderable();
}
public IRenderable createEquationRenderable()
{
return new EquationRenderable(val);
}
Test Case:
...
class Stubbed : SUT
{
boolean called = false;
public override EquationRenderable createEquationRenderable()
{
called=true;
return MyMock();
}
}
[Test]
public void test_new()
{
Stubbed sut = new Stubbed();
sut.GetRenderable();
assertTrue(sut.called);
// do further stuff on MyMock
}
I know, the example is overkill and a bit senseless, it is just for describing the idea. I am sure above could be shortcutted with mocking-frameworks for C#. Anyway testing the return-value direct output is more trivial and better approach here.
Maybe you have a more detailed example?
depending on the uniformity of your concrete IRenderable constructors you can use the following pattern for factory creating
public IRenderable CreateInstance<T>(object calculation) where T : IRenderable
{
Activator.CreateInstance<T>(new[] { calculation });
}
or if you have many different constructors you can use the params keyword to pass arbitrary amounts of arguments
public IRenderable CreateInstance<T>(params object[] args) where T : IRenderable
{
Activator.CreateInstance<T>(args);
}
To be able to do some kind of runtime check of the arguments you use this code before calling the Activator.CreateInstance
var types = args.Select(o => o.GetType()).ToArray();
var c = typeof(T).GetConstructor(types);
if (c == null)
{
throw new InvalidOperationException("No matched constructor")
}
A better way may be to simply unit test the code as is instead of refactoring it. Technically, this can be done by using a suitable mocking tool such as TypeMock Isolator or Microsoft Moles (there is a third one which I don't remember now).

c# delegate and abstract class

I currently have 2 concrete methods in 2 abstract classes. One class contains the current method, while the other contains the legacy method. E.g.
// Class #1
public abstract class ClassCurrent<T> : BaseClass<T> where T : BaseNode, new()
{
public List<T> GetAllRootNodes(int i)
{
//some code
}
}
// Class #2
public abstract class MyClassLegacy<T> : BaseClass<T> where T : BaseNode, new()
{
public List<T> GetAllLeafNodes(int j)
{
//some code
}
}
I want the corresponding method to run in their relative scenarios in the app. I'm planning to write a delegate to handle this. The idea is that I can just call the delegate and write logic in it to handle which method to call depending on which class/project it is called from (at least thats what I think delegates are for and how they are used).
However, I have some questions on that topic (after some googling):
1) Is it possible to have a delegate that knows the 2 (or more) methods that reside in different classes?
2) Is it possible to make a delegate that spawns off abstract classes (like from the above code)? (My guess is a no, since delegates create concrete implementation of the passed-in classes)
3) I tried to write a delegate for the above code. But I'm being technically challenged:
public delegate List<BaseNode> GetAllNodesDelegate(int k);
GetAllNodesDelegate del = new GetAllNodesDelegate(ClassCurrent<BaseNode>.GetAllRootNodes);
I got the following error:
An object reference is required for the non-static field, method, property ClassCurrent<BaseNode>.GetAllRootNodes(int)
I might have misunderstood something... but if I have to manually declare a delegate at the calling class, AND to pass in the function manually as above, then I'm starting to question whether delegate is a good way to handle my problem.
Thanks.
The way you're attempting to use delegates (constructing them with new, declaring a named delegate type) suggests that you're using C# 1. If you're actually using C# 3, it's much easier than that.
Firstly, your delegate type:
public delegate List<BaseNode> GetAllNodesDelegate(int k);
Already exists. It's just:
Func<int, List<BaseNode>>
So you don't need to declare your own version of it.
Secondly, you should think of a delegate as being like an interface with only one method in it, and you can "implement" it on the fly, without having to write a named class. Just write a lambda, or assign a method name directly.
Func<int, List<BaseNode>> getNodesFromInt;
// just assign a compatible method directly
getNodesFromInt = DoSomethingWithArgAndReturnList;
// or bind extra arguments to an incompatible method:
getNodesFromInt = arg => MakeList(arg, "anotherArgument");
// or write the whole thing specially:
getNodesFromInt = arg =>
{
var result = new List<BaseNode>();
result.Add(new BaseNode());
return result;
};
A lambda is of the form (arguments) => { body; }. The arguments are comma-separated. If there's only one, you can omit the parentheses. If it takes no parameters, put a pair of empty parentheses: (). If the body is only one statement long, you can omit the braces. If it's just a single expression, you can omit the braces and the return keyword. In the body, you can refer to practically any variables and methods from the enclosing scope (apart from ref/out parameters to the enclosing method).
There's almost never any need to use new to create a delegate instance. And rarely a need to declare custom delegate types. Use Func for delegates that return a value and Action for delegates that return void.
Whenever the thing you need to pass around is like an object with one method (whether an interface or a class), then use a delegate instead, and you'll be able to avoid a lot of mess.
In particular, avoid defining interfaces with one method. It will just mean that instead of being able to write a lambda to implement that method, you'll have to declare a separate named class for each different implementation, with the pattern:
class Impl : IOneMethod
{
// a bunch of fields
public Impl(a bunch of parameters)
{
// assign all the parameters to their fields
}
public void TheOneMethod()
{
// make use of the fields
}
}
A lambda effectively does all that for you, eliminating such mechanical patterns from your code. You just say:
() => /* same code as in TheOneMethod */
It also has the advantage that you can update variables in the enclosing scope, because you can refer directly to them (instead of working with values copied into fields of a class). Sometimes this can be a disadvantage, if you don't want to modify the values.
You can have a delegate that is initialized with references to different methods depending on some conditions.
Regarding your questions:
1) I'm not sure what you mean under "knows". You can pass any method to the delegate, so if you can write method that "knows" about some other methods than you can do a similar delegate.
2) Again, delegates can be created from any method that can be executed. For example if you have an initialized local variable of type ClassCurrent<T> you can created delegate for any instance method of type ClassCurrent<T>.
3) Delegate can call only the method that actually can be called. I mean that you cannot call ClassCurrent.GetAllRootNodes because GetAllRootNodes is not a static method, so you need an instance of the ClassCurrent to call it.
The delegate can stay in any class that has access to the ClassCurrent and MyClassLegacy.
For example you can create smth like:
class SomeActionAccessor<T>
{
// Declare delegate and fied of delegate type.
public delegate T GetAllNodesDelegate(int i);
private GetAllNodesDelegate getAllNodesDlg;
// Initilaize delegate field somehow, e.g. in constructor.
public SomeActionAccessor(GetAllNodesDelegate getAllNodesDlg)
{
this.getAllNodesDlg = getAllNodesDlg;
}
// Implement the method that calls the delegate.
public T GetAllNodes(int i)
{
return this.getAllNodesDlg(i);
}
}
The delegates can wrap both static and instance method. The only difference is that for creation delegate with instance method you need instance of the class who owns the method.
Let both ClassCurrent and MyClassLegacy implement an interface INodeFetcher:
public interface INodeFetcher<T> {
List<T> GetNodes(int k);
}
For ClassCurrent call the GetAllRootNodes method from the interface's implementation and for MyLegacyClass the GetAllLeaveNodes method.
Why would you want a delegate for this? It sounds overly complex. I would just create a method in a new class that you could instansiate when you needed to call you method. This class could be given some context information to help it decide. Then I would implement logic in the new method that would decide whether to call the current method or the legacy method.
Something like this:
public class CurrentOrLegacySelector<T>
{
public CurrentOrLegacySelector(some type that describe context)
{
// .. do something with the context.
// The context could be a boolean or something more fancy.
}
public List<T> GetNodes(int argument)
{
// Return the result of either current or
// legacy method based on context information
}
}
This would give you a clean wrapper for the methods that is easy to read and understand.
As a variation of the theme suggested by Rune Grimstad I think you could use the strategy pattern (e.g.
Introduction to the GOF Strategy Pattern in C# ).
This would be especially interesting in the case where you cannot change the LegacyClass (and therefore maybe cannot easily use the "interface approach" suggested by Cornelius) and if you are using dependency injection (DI; Dependency injection). DI would (maybe) let you inject the correct implementation (concrete strategy) in the right place.
Strategy:
public interface INodeFetcher<T> {
List<T> GetNodes(int k);
}
Concrete Strategies:
public class CurrentSelector<T> : INodeFetcher<T>
{
public List<T> GetNodes(int argument)
{
// Return the result "current" method
}
}
public class LegacySelector<T> : INodeFetcher<T>
{
public List<T> GetNodes(int argument)
{
// Return the result "legacy" method
}
}
-> Inject/instantiate the correct concrete strategy.
Regards

Categories

Resources