Consider next situation -
public class Derived : Base{
X(ParamX){} // xx method
X(ParamY){} // xy
}
public abstract class Base {
InvokeX(IParametr param){
...some magic
}
}
public class ParamX : IParametr {}
public class ParamY : IParametr {}
Can I invoke xx method using Derived.InvokeX(ParamX) ?
I know that I can do something like this (checked when InvokeX is in derived class, not shure for abstract):
InvokeX(IParametr #param){
((dynamic) this).X((dynamic) #param);
}
but I am looking for more faster solutions. Can I use in some way System.Runtime.CompilerServices namespace and in particular CallSite Class?
Thanks.
You have an instance of the Expression Problem, an extensibility problem common in most programming languages today. Reflection or dynamic invocation is a way around it, but it is prone to bugs, since you will not notice a mistake in naming or parameter types until you run the code down that specific path.
You want to extend your application to support more types (more implementations of IParametr) and also more operations (in this case more methods using types of parameters).
So basically you will get a matrix of types and operations. E.g.
Type Derived Derived2 ...
ParamX x x
ParamY x
...
The Xes represent requiring the implementation in the type (column) of the operation (row).
To keep the implementation type safe you need to use either the Visitor or the Interpreter pattern. Each has its drawbacks.
The visitor pattern, utilizing double dispatch:
public class Derived : Base {
public override void X(ParamX x) { }
public override void X(ParamY a) { }
}
public abstract class Base : IXVisitor
{
public void Visit(IParametr parameter)
{
parameter.Accept(this);
}
public abstract void X(ParamX x);
public abstract void X(ParamY a);
}
public interface IXVisitor
{
void X(ParamX a);
void X(ParamY a);
}
public interface IParametr
{
void Accept(IXVisitor visitor);
}
public class ParamX : IParametr
{
public void Accept(IXVisitor visitor)
{
visitor.X(this);
}
}
public class ParamY : IParametr
{
public void Accept(IXVisitor visitor)
{
visitor.X(this);
}
}
If you'd like to get really hardcore you can try Object Algebras
Related
I am currently working on a Service Fabric solution where data gets sent from one sevice to the next service.
I am sending class with several properties. this class is a sort of datatransfer object. I want to use a solid approach to prevent the use of integers which lead to switch logic.
ie. I don't want this:
public void ExecuteFunctionForType(IntegerTypedClass myClass, IInterface myinterface)
{
switch(myClass.typeInt)
{
case 1:
// Do shizzle for type 1
myinterface.execute1();
break;
case 2:
// do shizzle for type 2
myinterface.execute2();
break;
}
}
Instead i want to implement a SOLID approach. The one that comes to mind is shown below:
public abstract class AbstractTypedClass
{
public abstract void ExecuteInheritedFunction(IInterface myinterface);
}
public class FirstTypedClass : AbstractTypedClass
{
public override void ExecuteInheritedFunction(IInterface myinterface)
{
// do shizzle for the first typed class
myinterface.execute1();
}
}
public class SecondTypedClass : AbstractTypedClass
{
public override void ExecuteInheritedFunction(IInterface myinterface)
{
// do shizzle for the second typed class
myinterface.execute2();
}
}
The problem with this approach is that the AbstractTypedClass and all it's children will have a dependency on the IInterface, which I don't want. This is due to the fact that it's a service fabric interface which brings a lot of other dependencies with it.
I would prefer to have a solution where you can use the solid principle and not create a dependency on different libraries which will clutter up my solution
Things I can't use:
partial classes, because they need to be in the same assemvly
extension methods, because the default method gets called:
public static class TypedClassExtensions
{
public static void executeExtension(this AbstractTypedClass request, IInterface myinterface)
{
throw new NotImplementedException();
}
public static void executeExtension(this FirstTypedClass request, IInterface myinterface)
{
myinterface.execute1();
}
}
// when calling the code like so, the not implemented exception is thrown:
public void execute(AbstractTypedClass myclass, IInterface myinterface)
{
myclass.executeExtension(myinterface);
}
In C# 7 you can use pattern matching to avoid using the strategy or visitor patterns. This results in cleaner code because you don't have to add the same methods to all concrete classes, or use double dispatch.
void ExecuteFunctionForType(AbstractTypedClass myClass, IInterface myinterface)
{
switch(myClass)
{
case FirstTypedClass it1:
// Do shizzle for type 1
myinterface.execute1(it1.Prop1);
break;
case SecondTypedClass it2:
// do shizzle for type 2
myinterface.execute2(it2.Prop2);
break;
}
}
Assuming the interface and implementation look like this:
interface IInterface {void execute1(string input);void execute2(int input);}
class SomeClass:IInterface
{
public void execute1(string input) => Console.WriteLine($"1 {input}");
public void execute2(int input) => Console.WriteLine($"2 {input}");
}
and the classes like this:
public abstract class AbstractTypedClass{ }
public class FirstTypedClass : AbstractTypedClass
{
public string Prop1 =>"First";
}
public class SecondTypedClass : AbstractTypedClass
{
public int Prop2 =>500;
}
You can call a different method per type with a switch statement that performs pattern matching on types. The following code :
var it=new SomeClass();
ExecuteFunctionForType(new FirstTypedClass(),it);
ExecuteFunctionForType(new SecondTypedClass(),it);
Will produce :
1 First
2 500
Pattern matching on type returns a strongly typed variable of the matching type. The members of each concrete type can be used without requiring a definition on an interface or abstract class.
Using SOLID principles I would think your approach would look like this:
The dependency inversion principle recommends that you only depend on the interfaces you need for the function. So on your abstract class, I would simple make it generic and define the dependencies in the implementations of your abstract class. This way if you can implement different versions in different assemblies and those assemblies wouldn't have needless dependencies.
// ------------ Assembly A -----------------
public abstract class AbstractTypedClass<T>
{
public abstract void ExecuteInheritedFunction(T obj);
}
// ------------ Assembly B -----------------
IHugeDependency
{
void execute1();
...more
}
public class FirstTypedClass : AbstractTypedClass<IHugeDependency>
{
public override void ExecuteInheritedFunction(IHugeDependency obj)
{
// do shizzle for the first typed class
obj.execute1();
}
}
// ------------ Assembly C -----------------
ISmallerDependency
{
void execute2();
}
public class SecondTypedClass : AbstractTypedClass<ISmallerDependency>
{
public override void ExecuteInheritedFunction(ISmallerDependency obj)
{
// do shizzle for the second typed class
obj.execute2();
}
}
Using this approach Assembly B and C both have a dependency on A but B & C don't have a dependency on each other for no reason.
Maybe this is a dumb question. But, I don't get the point what I am missing.
Given the following class-definition
public abstract class AbstractBaseClass
{
public abstract void Create(AnotherAbstractClass param1);
}
Wheras AnotherAbstractClass is defined
public abstract class AnotherAbstractClass
{
}
with a concrete implementation
public class AnotherConcreteImplementation : AnotherAbstractClass
{
}
I want to be able to have the override of the Create method to use a concrete type:
public class ConcreteImplementation : AbstractBaseClass
{
public override void Create(AnotherConcreteImplementation param1) <-- There is no suitable method for override
{
// param1 is an instance of the concrete implementation
}
public override void Create(AnotherAbstractClass param1) <-- this is working but I'll have to cast on each implementation
{
// param1 is an instance of the abstract class and needs a cast
}
}
Is this simply not possible or is there some way I'm not aware of? Maybe using generics?
Edit #1 (added more context)
I'm trying to achieve/enforce that in a concrete implementation there is only one parameter valid.
Think of it like it's a database-layer. The Create method will create a new entry in the database. As of each table has different values, the create-parameter also has.
The casting inside smells (in my opinion) as of it can be called with any concrete implementation of AnotherAbstractClass.
public class AddressTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteAddressCreate)param1;
}
}
public class CityTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteCityCreate)param1;
}
}
Having an instance of AddressTable I can call
addressIntance.Create(new ConcreteAddressCreate()); // would be okay
on the other hand I can call it
addressIntance.Create(new ConcreteCityCreate()); // would be okay but will fail at runtime with InvalidCastException
Edit #2 (additional info)
It should also be possible to extend the AbstractBaseClass class with more abstract methods later.
So, for me it's more likely to have generic methods instead of an concrete class-implemenation with 200 generic parameters for each method to implement.
It violates the Liskov Substitution Principle so it makes perfect sense you can't do this. Namely, you can't just "have" covariance like this for free:
AbstractBaseClass bcl = new ConcreteImplementation();
bcl.Create(new DifferentImplementationWithoutSecondAbstract());
The contract AbstractBaseClass defines makes Create have to work with any implementation of AbstractBaseClass passed in - if you give a constraint on what can be passed in you've violated the contract it defines.
Like you assumed - you can use generics:
// notice the recursive definition, we require the generic parameter
// to be a generic parameter of itself - allowing AbstractBaseClass
// to not be aware of its subclasses like in the other answers.
public abstract class AbstractBaseClass<T> where T : AbstractBaseClass<T>
{
public abstract void Create(T param1);
}
public class Concrete : AbstractBaseClass<Concrete>
{
public override void Create(Concrete param1)
{
Console.WriteLine("Hello!");
}
}
Yes, you can do that using generics:
public abstract class AbstractBaseClass<T>
where T : AnotherAbstractClass
{
public abstract void Create(T param1);
}
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1)
{
}
}
Generics is indeed the way to do it.
public abstract class AbstractBaseClass<TDerivedClass> where TDerivedClass : AnotherAbstractClass
{
public abstract void Create(TDerivedClass param1);
}
And then you can do:
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1) // Works because TDerivedClass = AnotherConcreteImplementation
{
...
}
}
While there are plenty of example on generics using primitve types like int ans string I couldn't really find one using proper classes. Here is the scenario
//main program
class Program
{
static void Main(string[] args)
{
MyClass<TClass> mt = new MyClass<TClass>();
mt.GetValueFromType();
Console.ReadKey();
}
}
This is the generic class
public class MyClass<T>
{
public void GetValueFromType()
{
Console.WriteLine("Genric method called");
//Need to call the method MyTypeMethod() from the reference type sent in here.
//How?
}
}
One of the types that will be sent in to the generic class as
public class TClass
{
public void MyTypeMethod()
{
Console.WriteLine("Type method called");
}
}
Can this even be done in C# or do I need to refer to an interface of TClass with the new MyClass<T>().GetValueFromType() method ?
If I have to use interface then why use generics at all?
All the compiler can infer is that generic parameter T is of type Object so only the methods and properties for System.Object will be available. In order to get beyond that, you need to tell the compiler that T is expected to be derived from a base type, or implements specific interfaces. This is called a generic constraint:
public abstract class BaseClass
{
public virtual void MyTypeMethod()
{
}
}
public class TClass : BaseClass
{
public override void MyTypeMethod()
{
Console.WriteLine("Type method called");
}
}
public class MyClass<T> where T: BaseClass
{
public void GetValueFromType(T value)
{
Console.WriteLine("Genric method called");
value.MyTypeMethod();
}
}
So in this example any class derived from BaseClass can be used for the generic parameter T. You can also do the same thing with an interface. But in that case it would be more along the lines of that T implements the constrained interface. Usually the interface route is much more flexible since c# does not allow multiple inheritance.
You can use generic constrains what I think will accomplish what your after:
public class MyClass<T> where T: TClass
{
public void GetValueFromType(T value)
{
Console.WriteLine("Genric method called");
value.MyTypeMethod();
}
}
I'd create an abstract base class, say MyBase that defines the method MyTypeMethod():
public abstract class MyBase
{
public virtual void MyTypeMethod() { }
}
All the classes you want to use in the generic class would inherit from this. Override and implement MyTypeMethod()
Modify your generic class:
public class MyClass<T> where T : MyBase
{
public void GetValueFromType()
{
T.MyTypeMethod();
Console.WriteLine("Generic method called");
}
}
You could also use an interface as gleng suggested.
I've the following scenario
I've an Interface
public interface ImyInterface
{
void myInterfaceMethod(string param);
}
I've an Abstract Class
public abstract class myAbstractClass
{
public myAbstractClass()
{
//something valid for each inherited class
}
public void myAbstractMethod<T>(T param)
{
//something with T param
}
}
I've a class that inherits from myAbstractClass and implements ImyInterface
public class myClass : myAbstractClass, ImyInterface
{
public myClass():base()
{}
public void ThisMethodWillNeverCall()
{
// nothing to do
}
}
And, finally, I've a class where I'll create a ImyInterface object. At this point I would call myAbstractMethod, but...
public class myFinalClass
{
public void myFinalMethod()
{
ImyInterface myObj = _myContainer<ImyInterface>();
myObj.???
}
}
Obviously there isn't this method because it isn't declared into the interface.
My solution is the following
public interface ImyInterface
{
void myInterfaceMethod(string param);
void myFakeMethod<T>(T param);
}
public class myClass : myAbstractClass, ImyInterface
{
public myClass():base()
{}
public void ThisMethodWillNeverCall()
{
// nothing to do
}
//--- a fake method
public void myFakeMethod<T>(T param)
{
base.myAbstractMethod<T>(param);
}
}
Is there any other solution better than mine?
Thank you!
First of all, your naming convention is a mess. Read up on the guidelines that Microsoft have made.
It's also hard to tell what you are trying to achieve based on your example.
Back to your question:
You should only access an interface to work with that interface. Don't try to make any magic stuff with classes/interfaces to get them working together. That usually means that the class shouldn't try to implement the interface.
It's better that you create a new interface which have the features that you want and let your class implement both.
I am trying to define an interface and classes which implement the interface as below. The method defined in the interface accepts a string as argument where myClass2 implementation of the method Execute takes 2 arguments which doesn't follow the interface definition.
That's the problem. How could I define a method within an interface which takes n number of parameters of various type?
Please advice. Thanks.
public interface MyInterface
{
void Execute(string a);
}
public class myClass1 : MyInterface
{
public void Execute(string a)
{
Console.WriteLine(a);
}
}
public class myClass2 : MyInterface
{
public void Execute(string a, int b)
{
Console.WriteLine(a);
Console.WriteLine(b.ToString());
}
}
EDIT: I am thinking of another approach. I appreciate if someone could tell me if this will be a better design.
public interface IParameter
{
Type ParameterType { get; set; }
string Name { get; set; }
object Value { get; set; }
}
public interface MyInterface
{
void Execute(Recordset recordSet, List<IParameter> listParams);
}
public class MyClass : MyInterface
{
public void Execute(Recordset recordSet, List<IParameter> listParams)
{
}
}
I am passing a list of IParameter which holds all the required parameters which need to be sent.
How would the caller know how to call the method, if the interface didn't fix the parameter types?
The closest you can can would be:
public interface MyInterface
{
void Execute(params object[] args);
}
Implementations of the interface would have to then deal with any number of arguments being passed in though - you couldn't have an implementation which only handled a single int parameter, although it could of course throw an exception if args contains anything other than a single int value.
EDIT: Just to be clear, this would rarely be a good design. In some very weakly typed scenarios it may be appropriate, but otherwise, usually it would be worth trying to find something better.
If you can give more information about what you're trying to do, we may be able to help you more.
You can't do this for good reason. Different implementations of interfaces are meant to be used interchangeably. Your proposed design violates this principle. If you want help solving the conflict I think you need to explain what led you to this design.
So you're defining your interface as
public interface MyInterface
{
void Execute(string a);
}
and attempting to implement it as
public void Execute(string a, int b)
{
...
}
That won't work - you're declaring one interface, and attempting to define something else.
What might work (and I can't tell based on your post thus far) is explicit interface implementation - that is, your concrete object could expose an Execute(string, int) method and explicitly implement your interface method. Something like
public class myClass2 : MyInterface
{
public void Execute(string a, int b)
{
...
}
void MyInterface.Execute(string a)
{
...
}
}
That said, I'd strongly advise that you rethink this design. The entire point of interfaces is that they expose a common programmatic surface to the rest of your code - breaking that contract stinks to high heaven, in terms of code-smells.
In addition to #Jon answer: considering that you are implementing an Interface, so you are architect, just don't use an interface but simple base class with overloaded virtual functions and in every concrete class ocerride it in a way you prefer.
EDIT:
I mean something like this: instead of using interface declare base class, a pseudocode!
public class MyCoolBase // a base CLASS and not interface
{
public virtual void Execute(string a)
{
//empty, or NotImplementedException, base on design decision
}
public virtual void Execute(double b)
{
//empty, or NotImplementedException, base on design decision
}
public virtual void Execute(int a, int b)
{
//empty, or NotImplementedException, base on design decision
}
}
public class MyCoolChildOne : MyCoolBase
{
public override void Execute(string a)
{
//concrete implementation
}
}
public class MyCoolChildTwo : MyCoolBase
{
public override void Execute(int a, int b)
{
//concrete implementation
}
}
and so on...
Bad: When you do something like this in the code
MyCoolBase myCoolBase = new MyCoolChildOne ();
myCoolBase...?(); // should be really sure which function you're going to call on this line
Good: You have strong types management, and no more object[] arrays, or multiple inheritance from more then one interface which you must override, instead in this case you cam even avoid it, even if I think it's not so good idea.
By the way, like geeks here said, I don't think your architecture is very reliable, there should be some other solution around for you. We just try to find out the best choice looking on code and question, but real problem can know only you.
Hope this helps.
Regards.
You can do that with weakly typed approach. E.g., you could define an interface that takes objects array:
public intrface MyInterface
{
void Execute(params object[] args);
}
And than you can call any of your concrete class with any arguments:
myClass.Execute("string", 1);
But in this case you violate the main purpose of interfaces, inheritance and compile-time checks.
Another way to implement this is to achieve this is to encapsulate all parameters in additional class hierarchy:
class CommandData
{
public string StringData {get; set;}
}
class ExtendedCommandData : CommandData
{
public int I {get;set;}
}
interface IMyInterface
{
public void Execute(CommandData commandData);
}
class MyClass1 : IMyInterface
{
public void Execute(CommandData commandData);
}
class MyClass2 : IMyInterface
{
// Lets impelment this interface explicitely
void IMyInterface.Execute(CommandData commandData)
{
}
void Execute(ExtendedCommandData extendedData)
{
// now we can access to string and int parameter
}
}
For what it's worth, this might be a great use case for generics.
You define the minimum required parameters as properties of an interface, then inherit where more parameters are required.
Looks quite silly when you're only using 1 parameter in the base interface, but of course this concept could be expanded to more complex types.
public interface MyInterface<T> where T : ParamA
{
void Execute(T paramA);
}
public interface ParamA
{
string ParameterA { get; }
}
public class myClass1 : MyInterface<myClass1.myParamA>
{
public class myParamA : ParamA
{
public string ParameterA { get; set; }
}
public void Execute(myParamA a)
{
Console.WriteLine(a.ParameterA);
}
}
public class myClass2 : MyInterface<myClass2.myParamsAb>
{
public class myParamsAb : ParamA
{
public string ParameterA { get; set; }
public int ParameterB { get; set; }
}
public void Execute(myParamsAb ab)
{
Console.WriteLine(ab.ParameterA);
Console.WriteLine(ab.ParameterB.ToString());
}
}