The short version of what I am looking for is this:
I am looking for a mechanism which, given an interface, will dynamically generate a pair of classes for that interface, one multiplexer and one demultiplexer, which will convert calls to/from a general-purpose delegate of the following form: object AnyCall( int method_selector, object[] arguments ). The multiplexer class will accept an AnyCall delegate as a construction-time parameter, and it will implement the interface by delegating every call to the delegate. The demultiplexer class will accept a reference to the interface as a construction-time parameter, and it will implement the delegate by switching on the method selector and invoking the appropriate method of the interface, passing it the parameters that were passed to the delegate.
The long version of what I am looking for is this:
Consider the following interface:
public interface IFooable
{
void Moo( int i );
void Boo( string s, bool b );
}
And consider the following class implementing that interface:
public class FooImplementation: IFooable
{
void IFooable.Moo( int i ) { System.Console.WriteLine( "i: " + i ); }
void IFooable.Boo( string s, bool b ) { System.Console.WriteLine( "s: " + s + ", b: " + b ); }
}
And then consider the following class making use of the above:
public partial class MuxdemTest
{
public static void InvokeFoo( IFooable fooable )
{
fooable.Moo( 42 );
fooable.Boo( "fubar!", true );
}
public static void Run1()
{
IFooable fooable = new FooImplementation();
InvokeFoo( fooable );
}
}
Nothing fancy here.
Now let us suppose that instead of giving InvokeFoo() a direct reference to FooImplementation I would like to embed some functionality inbetween the two that would allow me to do some really useful things with the interface method calls, like, say, count the number of times a call was made to one of the methods of the interface; or convert the calls into messages and deliver them to a FooImplementation that resides on a different thread; or on a different continent; or whatever. And of course this inbetween functionality should be able to work on ANY interface, not just IFooable.
In order to achieve this, we need a way to multiplex calls to methods of an interface into invokations of a single general-purpose delegate, and later demultiplex them from invokations to that delegate into interface method calls. The delegate I am thinking of would have the following form:
public delegate object AnyCall( int method_selector, object[] arguments );
So, here is an implementation of a multiplexer for the IFooable interface:
public class MuxForFooable: IFooable
{
private readonly AnyCall AnyCall;
public MuxForFooable( AnyCall anycall ) { AnyCall = anycall; }
void IFooable.Moo( int i ) { AnyCall( 0, new object[]{ i } ); }
void IFooable.Boo( string s, bool b ) { AnyCall( 1, new object[]{ s, b } ); }
}
And here is an implementation of a demultiplexer for the IFooable interface:
public class DemuxForFooable
{
public readonly IFooable Target;
public DemuxForFooable( IFooable target ) { Target = target; }
public object AnyCall( int method_selector, object[] arguments )
{
switch( method_selector )
{
case 0: Target.Moo( (int)arguments[0] ); break;
case 1: Target.Boo( (string)arguments[0], (bool)arguments[1] ); break;
default: throw new System.InvalidOperationException();
}
return null;
}
}
And here is a piece of code that makes use of the above, achieving exactly the same thing as the Run1() method above, the difference now being that all calls pass through an 'AnyCall' delegate:
public partial class MuxdemTest
{
public static void Run2()
{
IFooable fooable = new FooImplementation();
DemuxForFooable demux = new DemuxForFooable( fooable );
MuxForFooable mux = new MuxForFooable( demux.AnyCall );
InvokeFoo( mux );
}
}
My only problem is that the classes MuxForFooable and DemuxForFooable have been hand-written, while I want them dynamically generated. Consider the following mock methods that would generate them, and a piece of code that would use those methods:
public partial class MuxdemTest
{
public static T CreateMux<T>( AnyCall anycall )
{
if( typeof(T) == typeof(IFooable) )
return (T)(IFooable)new MuxForFooable( anycall );
throw new System.NotImplementedException();
}
public static AnyCall CreateDemux<T>( T target )
{
if( typeof(T) == typeof(IFooable) )
return new DemuxForFooable( (IFooable)target ).AnyCall;
throw new System.NotImplementedException();
}
public static void Run3()
{
IFooable fooable = new FooImplementation();
AnyCall demux = CreateDemux<IFooable>( fooable );
IFooable mux = CreateMux<IFooable>( demux );
InvokeFoo( mux );
}
}
Run3() above has exactly the same effect as Run2() and Run1() further above.
So, has anyone ever written or knows how to write actual implementations for CreateMux() and CreateDemux()?
You may assume that the interfaces will contain only methods and no properties, and that all methods will return void and will not accept any "ref" nor "out" parameters. (Even though I would not mind an implementation that would allow these things.)
There are lots of code samples out there that do things similar to what I want, but I am posting this question in the hope that someone has already done exactly what I want to do, because the subject of dynamic code generation is very tricky.
I am aware that what I want can be accomplished with existing proxy frameworks like CastleProxy, but I do not want to use an entire external framework for such a simple task, nor do I want the runtime overhead incurred by the use of such a framework. I looked at the source code of CastleProxy trying to figure out how to use parts of it to do what I want, but I found it way too convoluted to make any sense out of it.
Edit 1:
Six months later, I implemented a tool which does what I was asking for in this question. I am going to publish a paper about it, but before I do that, I need help with the naming, so I opened another question: Need help with naming (marshaling interface calls)
In the mean time, please feel free to add an answer if you have one.
Edit 2:
I decided to call the tool "intertwine", and the operations "entwine" and "untwine". If you want to read about it, here it is: michael.gr - Intertwine: Normalizing Interface Invocations
In order to achieve this, we need a way to multiplex calls to methods of an interface into invokations of a single general-purpose delegate, and later demultiplex them from invokations to that delegate into interface method calls.
I don't see how this follows from your requirements. I think what you actually want is DynamixProxy, or something similar. With it you can intercept calls to methods, which seems to be exactly what you want. Simple example:
class LoggingIntereceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine(invocation.Method);
invocation.Proceed();
}
}
…
public static void Run1()
{
var generator = new ProxyGenerator();
IFooable fooable = generator.CreateInterfaceProxyWithTarget<IFooable>(
new FooImplementation(), new LoggingIntereceptor());
InvokeFoo(fooable);
}
This gives the following output:
Void Moo(Int32)
i: 42
Void Boo(System.String, Boolean)
s: fubar!, b: True
DynamicProxy generates a type that implements the interface at runtime, so it should be quite fast.
If you don't want to add “an entire framework” to your projects, you don't have to. What you need to run the example above is only one additional assembly: Castle.Core.dll.
I just read oracle.com: Dynamic Proxy Classes and found out that the java runtime environment offers half of what I am looking for. In their own words:
A dynamic proxy class is a class that implements a list of interfaces
specified at runtime such that a method invocation through one of the
interfaces on an instance of the class will be encoded and dispatched
to another object through a uniform interface.
The relevant facility is in the java.lang.reflect package: The Proxy class creates multiplexers, and the InvocationHandler interface plays the role of my AnyCall delegate. Java does not appear to offer any means of creating demultiplexers; why, I do not know.
Related
I'm trying to restrict the return type of a generic delegate without specifying the parameter signature, and I don't know how to do this, or if it is even possible.
How can I do this or is it impossible?
My research has come up dry. Some pseudo-C# code would probably help steer you toward what I'm trying to do:
public class SomeClass< T, U > where T : Delegate // returning U
{
private someDelegate;
public SomeClass( T someDelegate )
{
this.someDelegate = someDelegate;
}
public U Run()
{
return someDelegate.DynamicInvoke();
}
}
... Elsewhere
public delegate string aDelegate();
public static string SayHi()
{
return "Hello!";
}
aDelegate greeter = SayHi;
var something = new SomeClass< aDelegate, string>( greeter );
Console.WriteLine( something.Run() ); // Should write "Hello" to the console.
I know this is a rather contrived pseudo example. I aim for a more involved usage, of course. I'm trying to write a console menu class that would associate a list of given menu options with actions that would fire depending on what option the user chooses. Right now, it just returns the string the user chose from the menu. What I'd like be able to do is return what--if anything--the associated method returns. This could perhaps be returned with the user chosen option string in a tuple... But, I figured this mini-example just cut straight to the technical hurdle I'm experiencing.
Thanks!
.NET already defines a generic delegate that returns the generic argument as it's result, Func<T>. You don't even need to define it.
public class SomeClass<U>
{
private Func<U>;
public SomeClass(Func<U> someDelegate)
{
this.someDelegate = someDelegate;
}
public U Run()
{
return someDelegate();
}
}
There's no real useful reason to allow a user of the type to provide any arbitrary delegate of the same signature. Really I'd advise you to avoid using any delegates in your code other than Func and Action (with various different numbers of generic arguments) whenever possible, as it's just creating a hassle to do so. I would consider it a reasonable restriction on any caller that has a delegate of a different type but the same signature to simply convert it to a Func<T> anyway, it's not like it's even a difficult conversion for them.
If you don't want to use Func<T> (as Servy suggests), e.g. if you have a custom delegate of your own that you want to be passed with type-safety, then perhaps you can make your custom delegate generic with respect to its return type. Then you can do it this way:
public delegate T MyDelegate<T>();
public class Foo<T>
{
private readonly MyDelegate<T> _delegate;
public Foo(MyDelegate<T> handler)
{
_delegate = handler;
}
public T Bar()
{
return _delegate();
}
}
Sorry its a bit vague perhaps but its been bugging me for weeks. I find each project I tackle I end up making what I think is a design mistake and am pretty sure theres a bettwe way.
When defining a class thats serialized from an event source like a sinple json doc definition. Lets call it keys class with various defined integers, bools and strings. i have multiple methods that make use of this and i find that i constantly need to paas this class as an object by means of an overload. So method a calls methods b, method b doesnt need these objects but it calls method c which does... In doing this bad practice im passing these 'keys' objects to method b for the sole purpose of method c accessibility.
Im probably missing one major OOP fundamental :) any guidance or reading would be appreciated as im googled out!!
public class Keys
{
public child Detail { get; set; }
}
public class child
{
public string instance { get; set; }
}
//my main entry point
public void FunctionHandler(Keys input, ILambdaContext context)
{
methodA(input)
}
static void methodA(Keys input)
{
//some-other logic or test that doesn't need Keys object/class if (foo==bar) {proceed=true;}
string foo = methodB(input)
}
static string methodB(Keys input)
{
//here i need Keys do do stuff and I return a string in this example
}
What you do is not necessarily bad or wrong. Remember that in C# what you actually pass are references, not objects proper, so the overhead of parameter passing is really small.
The main downside of long call chains is that the program logic is perhaps more complicated than it needs to be, with the usual maintainability issues.
Sometimes you can use the C# type system to let the compiler or the run time choose the proper function.
The compiler is employed when you overload method() for two different types instead of defining methodA() and methodB(). But they are distinguished by the parameter type, so you need different Key types which may be (but don't have to be) related:
public class KeyA {/*...*/}
public class KeyB {/*...*/}
void method(KeyA kA) { /* do something with kA */ }
void method(KeyB kB) { /* do something with kB */ }
This is of limited benefit; that the functions have the same name is just syntactic sugar which makes it clear that they serve the same purpose.
The other, perhaps more elegant and versatile technique is to create an inheritance hierarchy of Keys which each "know" what a method should do.
You'll need a base class with a virtual method which will be overridden by the inheriting classes. Often the base is an interface just declaring that there is some method(), and the various implementing types implement a method() which suits them. Here is a somewhat lengthy example which uses a virtual Output() method so that we see something on the Console.
It's noteworthy that each Key calls a method of an OutputterI, passing itself to it as a parameter; the outputter class then in turn calls back a method of the calling object. That's called "Double Dispatch" and combines run-time polymorphism with compile-time function overloading. At compile time the object and it's concrete type are not known; in fact, they can be implemented later (e.g. by inventing another Key). But each object knows what to do when its callback function (here: GetData()) is called.
using System;
using System.Collections.Generic;
namespace DoubleDispatch
{
interface KeyI
{ // They actually delegate that to an outputter
void Output();
}
interface OutputterI
{
void Output(KeyA kA);
void Output(KeyExtra kE);
void Output(KeyI k); // whatever this does.
}
class KeyBase: KeyI
{
protected OutputterI o;
public KeyBase(OutputterI oArg) { o = oArg; }
// This will call Output(KeyI))
public virtual void Output() { o.Output(this); }
}
class KeyA : KeyBase
{
public KeyA(OutputterI oArg) : base(oArg) { }
public string GetAData() { return "KeyA Data"; }
// This will compile to call Output(KeyA kA) because
// we pass this which is known here to be of type KeyA
public override void Output() { o.Output(this); }
}
class KeyExtra : KeyBase
{
public string GetEData() { return "KeyB Data"; }
public KeyExtra(OutputterI oArg) : base(oArg) { }
/** Some extra data which needs to be handled during output. */
public string GetExtraInfo() { return "KeyB Extra Data"; }
// This will, as is desired,
// compile to call o.Output(KeyExtra)
public override void Output() { o.Output(this); }
}
class KeyConsolePrinter : OutputterI
{
// Note: No way to print KeyBase.
public void Output(KeyA kA) { Console.WriteLine(kA.GetAData()); }
public void Output(KeyExtra kE)
{
Console.Write(kE.GetEData() + ", ");
Console.WriteLine(kE.GetExtraInfo());
}
// default method for other KeyI
public void Output(KeyI otherKey) { Console.WriteLine("Got an unknown key type"); }
}
// similar for class KeyScreenDisplayer{...} etc.
class DoubleDispatch
{
static void Main(string[] args)
{
KeyConsolePrinter kp = new KeyConsolePrinter();
KeyBase b = new KeyBase(kp);
KeyBase a = new KeyA(kp);
KeyBase e = new KeyExtra(kp);
// Uninteresting, direkt case: We know at compile time
// what each object is and could simply call kp.Output(a) etc.
Console.Write("base:\t\t");
b.Output();
Console.Write("KeyA:\t\t");
a.Output();
Console.Write("KeyExtra:\t");
e.Output();
List<KeyI> list = new List<KeyI>() { b, a, e };
Console.WriteLine("\nb,a,e through KeyI:");
// Interesting case: We would normally not know which
// type each element in the vector has. But each type's specific
// Output() method is called -- and we know it must have
// one because that's part of the interface signature.
// Inside each type's Output() method in turn, the correct
// OutputterI::Output() for the given real type was
// chosen at compile time dpending on the type of the respective
// "this"" argument.
foreach (var k in list) { k.Output(); }
}
}
}
Sample output:
base: Got an unknown key type
KeyA: KeyA Data
KeyExtra: KeyB Data, KeyB Extra Data
b,a,e through KeyI:
Got an unknown key type
KeyA Data
KeyB Data, KeyB Extra Data
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);
}
I am setting up a testing component and trying to keep it generic. I want to use a generic Visitor class, but not sure about using descendant classes.
Example:
public interface Interface_Test_Case
{
void execute();
void accept(Interface_Test_Visitor v);
}
public interface Interface_Test_Visitor
{
void visit(Interface_Test_Case tc);
}
public interface Interface_Read_Test_Case
: Interface_Test_Case
{
uint read_value();
}
public class USB_Read_Test
: Interface_Read_Test_Case
{
void execute()
{ Console.WriteLine("Executing USB Read Test Case."); }
void accept(Interface_Test_Visitor v)
{ Console.WriteLine("Accepting visitor."); }
uint read_value()
{
Console.WriteLine("Reading value from USB");
return 0;
}
}
public class USB_Read_Visitor
: Interface_Test_Visitor
{
void visit(Interface_Test_Case tc)
{ Console.WriteLine("Not supported Test Case."); }
void visit(Interface_Read_Test_Case rtc)
{ Console.WriteLine("Not supported Read Test Case."); }
void visit(USB_Read_Test urt)
{ Console.WriteLine("Yay, visiting USB Read Test case."); }
}
// Code fragment
USB_Read_Test test_case;
USB_Read_Visitor visitor;
test_case.accept(visitor);
What are the rules the C# compiler uses to determine which of the methods in USB_Read_Visitor will be executed by the code fragment?
I'm trying to factor out dependencies of my testing component. Unfortunately, my current Visitor class contains visit methods for classes not related to the testing component. Am I trying to achieve the impossible?
Since your accept() method doesn't actually call any of the visit() methods, none. :)
However if you invoked it as:
void accept(Interface_Test_Visitor v)
{
Console.WriteLine("Accepting visitor.");
v.Visit(this); // lets invoke it this time
}
the compiler will see that this is first as an instance of USB_Read_Test, then Interface_Read_Test_Case, then Interface_Test_Case. It will choose the most direct overload first (or one where implicit conversions can be used) then go down the inheritance chain until it finds a suitable type that fits an overload. So in this case, it will call visit(USB_Read_Test). You can override this behavior by casting:
v.Visit((Interface_Read_Test_Case)this); // argument is an instance of Interface_Read_Test_Case
v.Visit((Interface_Test_Case)this); // argument is an instance of Interface_Test_Case
If however your class implements multiple interfaces, where each interface has an overload but there is none for the class, you will get ambiguity errors which you will have to resolve.
e.g.,
interface IX { }
interface IY { }
class Class : IX, IY { }
void Call(IX _) { }
void Call(IY _) { }
// no Call(Class _) method
var c = new Class();
Call(c); // error: ambiguous call
Call((IX)c); // not ambiguous
For more information, see Method resolution order and slightly related C#: Passing null to overloaded method - which method is called?.
Instead of defining an entire interface and associated implementations for Visiting, define a Visit method that accepts an Action (or Predicate, or Func depending on what you want the Visitor to do).
class TestCase
{
public void Visit(Action<T> action, T val)
{
action(val);
}
}
var tc = new TestCase();
uint some_val = 3;
tc.Visit((Action) (val) => Console.WriteLine("Val " + val));
Though I'm not entirely clear on what you're trying to do, defining a method that takes a Function can remove the necessity of defining all those interfaces.
As the comment says, accept doesnt invoke any visit methods, so I answer based on what i think you meant...
I would have thought it based on the declared type of the object passed in as a parameter?
USB_Read_Test obj1 = new USB_Read_Test();
Interface_Read_Test_Case obj2 = new USB_Read_Test();
invoking with both as parameters should result in visit(USB_Read_Test urt) for obj1, and visit(Interface_Read_Test_Case rtc) for obj2.
In my application I work with criterias. I have one base Criteria interface and and other interfaces who inherits from this base interface:
ICriteria
|
|
----------------------
| |
ITextCriteria IChoices
What I'd like to know is, what is the best way to know what Type the class is?
In my code I have a dropdown box and based on that I have to determine the type:
// Get selected criteria
var selectedCriteria = cmbType.SelectedItem as ICriteria;
if (selectedCriteria is IChoices)
{
//selectedCriteria = cmbType.SelectedItem as IChoices; Doesn't work
IChoices criteria = selectedCriteria as IChoices;//cmbType.SelectedItem as IChoices;
SaveMultipleChoiceValues(criteria);
//_category.AddCriteria(criteria);
}
else
{
//ICriteria criteria = selectedCriteria; //cmbType.SelectedItem as ICriteria;
if (selectedCriteria.GetCriteriaType() == CriteriaTypes.None)
{
return;
}
//_category.AddCriteria(criteria);
}
_category.AddCriteria(selectedCriteria);
selectedCriteria.LabelText = txtLabeltext.Text;
this.Close();
My question is, is this the best way? Or is there a better way to achieve this?
The chance is big that there are coming more interfaces based on ICriteria.
EDIT:
I have 2 types of controls which I want to add dynamically to my application. One control is a textbox and the other is a radio button.
For a radio button the user can define the options. When the options are defined, the user must choose one of the options and the chosen option must be saved in the database (this is later used to perform search operations). So, when the Save button is clicked, I have to determine the chosen type (radio or text) and save the answer possibilities (if it is a radio).
For a textbox, this doesn't have any answer possibilities. For that reason it has a different interface.
I hope I make it a little bit clearer now. Here is another question which is related: C# How to implement interface where concrete classes differs?
EDIT II:
This is how my method SaveMultipleChoiceValues looks like:
private void SaveMultipleChoiceValues(IChoices criteria)
{
foreach (DataGridViewRow row in dgvCriteriaControls.Rows)
{
if (row == dgvCriteriaControls.Rows[dgvCriteriaControls.Rows.Count - 1])
continue;
//multipleChoice.AddChoice(row.Cells["Name"].Value.ToString());
string choice = row.Cells["Name"].Value.ToString();
criteria.AddChoice(choice);
}
}
This looks like a prime example for polymorphism.
Instead of trying to do a type switch on your ICriteria implementation, why don't you add a method to ICriteria (or possibly a virtual method to some common base class of all ICriteria implementations), and just call that?
Obviously the implementation of this method would need access to objects that do not belong in your ICriteria instances, but that is a problem you can solve using other design patterns according to the specifics of your scenario.
Update:
Here's a complete solution, incorporating the code you posted:
Create a new interface ICriteriaView which models the view (in your case a Form) where ICriteria are displayed. The form needs to do some processing depending on the exact interface that criteria implement, so add a method with one overload for each interface that exists in your code. Do not add an overload for ICriteria itself. [1]
interface ICriteriaView {
void ProcessCriteria(IChoices criteria);
void ProcessCriteria(ITextCriteria criteria);
}
Your form will implement this interface, providing methods where suitable processing for each subtype of ICriteria will occur:
class MyForm : ICriteriaView {
public void ProcessCriteria(IChoices criteria) {
this.SaveMultipleChoiceValues(criteria);
}
public void ProcessCriteria(ITextCriteria criteria) {
// do nothing
}
private void SaveMultipleChoiceValues(IChoices criteria)
{
foreach (DataGridViewRow row in dgvCriteriaControls.Rows)
{
if (row == dgvCriteriaControls.Rows[dgvCriteriaControls.Rows.Count - 1])
continue;
//multipleChoice.AddChoice(row.Cells["Name"].Value.ToString());
string choice = row.Cells["Name"].Value.ToString();
criteria.AddChoice(choice);
}
}
}
Each implementation of ICriteria will need to implement a method which calls the appropriate ICriteriaView overload for its type. This is where the "redirection magic" happens: we will use polymorphism to get the compiler to "discover" the actual type of ICriteria our object is, and then use method overloading on ICriteriaView.ProcessCriteria to access the appropriate code.
interface ICriteria {
void PerformProcessingOn(ICriteriaView view);
}
interface IChoices : ICriteria {
}
interface ITextCriteria : ICriteria {
}
And this is where the dispatch to the appropriate overload happens:
class MultipleChoice : IChoices {
public PerformProcessingOn(ICriteriaView view) {
view.ProcessCriteria(this);
}
}
class SimpleInput : ITextCriteria {
public PerformProcessingOn(ICriteriaView view) {
view.ProcessCriteria(this);
}
}
Then, your code would do:
// Get selected criteria
var selectedCriteria = cmbType.SelectedItem as ICriteria;
// Here's where polymorphism kicks in
selectedCriteria.PerformProcessingOn(this);
// Finally, code that runs the same for all objects
_category.AddCriteria(selectedCriteria);
selectedCriteria.LabelText = txtLabeltext.Text;
this.Close();
Maintenance:
Whenever you add a new ICriteria sub-interface implementation, the definition of ICriteria will force you to implement the PerformProcessingOn method on it. Inside that method, all you can do really is call view.ProcessCriteria(this). In turn, this will force you to implement an appropriate ProcessCriteria overload in ICriteriaView and MyForm.
As a result, we have achieved two important objectives:
The compiler will not allow you to add a new ICriteria implementation without specifying exactly how that implementation should interact with ICriteriaView.
It is easy to discover from source code exactly what MyView does with e.g. IChoices when reading the code for MultipleChoice. The structure of the code leads you to MyForm.SaveMultipleChoiceValues "automatically".
Notes:
[1] The choice of adding an overload for ICriteria itself or not is really a tradeoff:
If you do add one, then code like this:
class MultipleChoice : IChoices {
public PerformProcessingOn(ICriteriaView view) {
view.ProcessCriteria(this);
}
}
will compile successfully always, because even if there is no ICriteriaView.ProcessCriteria(IChoices) overload there will still be the ICriteriaView.ProcessCriteria(ICriteria) overload that the compiler can use.
This means that, when adding a new ICriteria sub-interface implementation, the compiler will no longer force you to go check if the implementation of ICriteriaView.ProcessCriteria(ICriteria) really does the right thing for your new implementation.
If you do not add one, then the moment you write view.ProcessCriteria(this); the compiler will force you to go check (and update) ICriteriaView and MyForm accordingly.
In this scenario, and with the information you have provided, I believe that the appropriate choice would be the last one.
[2] As you can see above, the implementation of ICriteria.PerformProcessingOn inside MultipleChoice and SimpleInput looks exactly the same. If these two classes have a common base (which is quite possible in practice), you might be tempted to move the "duplicated" code into that base. Do not do that; it will cause the solution to break.
The tricky part is that inside MultipleChoice, when you do view.ProcessCriteria(this); the compiler can infer that the static type of this is IChoices -- this is where the redirection happens! If you move the call to ProcessCriteria inside a hypothetical base class CriteriaBase : ICriteria, then the type of this will become ICriteria and the dispatch of the call to the appropriate ICriteriaView.ProcessCriteria overload will no longer work.
You could do this:
var selectedCriteria = cmbType.SelectedItem as ICriteria;
if (typeof(IChoices).IsAssignableFrom(selectedCriteria.GetType()))
{
IChoices criteria = selectedCriteria as IChoices;
SaveMultipleChoiceValues(criteria);
}
else if(typeof(ITextCriteria).IsAssignableFrom(selectedCriteria.GetType()))
{
if (selectedCriteria.GetCriteriaType() == CriteriaTypes.None)
{
return;
}
}
But polymorphism is probably your best bet.
That is not the best way. If you are performing different actions based on the type of an object, you should probably be using polymorphism instead for a myriad number of reasons.
How you use polymorphism depends on what you actually need to have done based on the different types of ICriteria that are being used. If you just need to get a string containing all of their members, you could easily add a method to ICriteria and hand the responsibility to the class itself instead of the code that depends on it. This reduces duplication, puts code in a logical place, and makes sure you don't forget to add code for a new type of ICriteria.
If you give us more information on how you want different types to be treated/behave, we can probably give you more specific advice. :D
Here is a long term solution to an ever expanding list of critera without having to add more if/then/else.
While this code is complex to someone not used to designing in this manner, it allows you to keep your method dealing with criteria the same, and just register new delegates to handle additional criteria.
The idea is to create a map of Type objects that hold delegates in which to execute. You can then register new delegates to execute based on new Types as you generate them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Stackoverflow_4527626
{
delegate void CriteraDelegate(params object[] args);
class CriteraManager
{
private Dictionary<Type, CriteraDelegate> criterian = new Dictionary<Type, CriteraDelegate>();
public void RegisterCritera(Type type, CriteraDelegate del)
{
criterian[type] = del;
}
public void Execute(Object criteria, params object[] args)
{
Type type = criteria.GetType();
/// Check to see if the specific type
/// is in the list.
if (criterian.ContainsKey(type))
{
criterian[type](args);
}
/// If it isn't perform a more exhaustive search for
/// any sub types.
else
{
foreach (Type keyType in criterian.Keys)
{
if (keyType.IsAssignableFrom(type))
{
criterian[keyType](args);
return;
}
}
throw new ArgumentException("A delegate for Type " + type + " does not exist.");
}
}
}
interface InterfaceA { }
interface InterfaceB1 : InterfaceA { }
interface InterfaceB2 : InterfaceA { }
interface InterfaceC { }
class ClassB1 : InterfaceB1 { }
class ClassB2 : InterfaceB2 { }
class ClassC : InterfaceC { }
class Program
{
static void ExecuteCritera1(params object[] args)
{
Console.WriteLine("ExecuteCritera1:");
foreach (object arg in args)
Console.WriteLine(arg);
}
static void ExecuteCritera2(params object[] args)
{
Console.WriteLine("ExecuteCritera2:");
foreach (object arg in args)
Console.WriteLine(arg);
}
static void Main(string[] args)
{
CriteraDelegate exampleDelegate1 = new CriteraDelegate(ExecuteCritera1);
CriteraDelegate exampleDelegate2 = new CriteraDelegate(ExecuteCritera2);
CriteraManager manager = new CriteraManager();
manager.RegisterCritera(typeof(InterfaceB1), exampleDelegate2);
manager.RegisterCritera(typeof(InterfaceB2), exampleDelegate2);
manager.RegisterCritera(typeof(InterfaceC), exampleDelegate1);
ClassB1 b1 = new ClassB1();
ClassB2 b2 = new ClassB2();
ClassC c = new ClassC();
manager.Execute(b1, "Should execute delegate 2");
manager.Execute(b2, "Should execute delegate 2");
manager.Execute(c, "Should execute delegate 1");
}
}
}