once again I'm here for help. I'm writing my first "real-like" application to practice what I learned and I am not sure about my approach. I'll try to explain it as best as my english allows me.
Application consist of base abstract class and three classes inherited from that base.
abstract class BaseClass
{
// Some stuff...
// This method is used in all classes. It gets whole adb output
// and returns it as a string for future formating
protected string ProcessAdbCommand(string command)
{
try
{
_processInfo.Arguments = command;
Process adbProcess = Process.Start(_processInfo);
adbProcess.WaitForExit();
return adbProcess.StandardOutput.ReadToEnd();
}
catch (Exception e)
{
WriteToLog(e.Message);
return null;
}
}
}
After ProcessAdbCommand returns output, I will call another method which handles output as needed. Principle is always the same - format output and make somethinkg usefull based on the output.
Now I'd like to make clear, that method responsible for output handling needs to be in every inherited class. But problem is that in very class it returns different value type (boolean, List of IDevice and strings)
I am struggling here. First I wanted to make it protected abstract. Somethink like
abstract class BaseClass
{
// Some stuff...
// Same as above
protected string ProcessAdbCommand(string command)
{
//Same as above
}
//Method which will be implemented in every inherited class differently
protected bool|List<IDevice>|string ProcessAdbOutput(string adbOutput)
{
//Method implementation
return bool|List<IDevice>|string
}
}
But as I discovered it is not possible to override return type. And because method will be always used only internally in classes, I do not see reason to "force" it using interfaces.
After some time I game up and decided to forget about forcing implementation in derived classes and simply write them as I need. But do you think it is "legal" approach? How would you solve problem like that in "real world" application? Is there something I am still missing or is my approach simply wrong? Thank you.
Struggling Greenhorn.
One possible approach would be to make the abstract base class generic and accept a T parameter, which can also be the output of your ProcessAdbOutput method. Then, you make the method abstract to make sure any derived type has to implement it:
public abstract class BaseClass<T>
{
protected string ProcessAdbCommand(string command)
{
return string.Empty;
}
public abstract T ProcessAdbOutput(string result);
}
public class DerivedClass : BaseClass<IList<IDevice>>
{
public override IList<IDevice> ProcessAdbOutput(string result)
{
return new List<IDevice>();
}
}
Related
I have an abstract class called Flight and its implement a interface called IFlight and it has a virtual method, another three classes that inherit from it, the only diffrence between those three classes is the implemantation of this method. Another thing that I want to do is implement a method that accepts as an argument an object of type IFlight (could be one of those three classes) and from them i want to access the members of the abstract class (Flight). Which way there is to implement such thing ?
Flight:
class AbsFlight: IFlight
{
public int ID { get; set; }
public string Start_Point { get; set; }
public virtual float Calculate_Price(float Base_Price)
{
return Base_Price;
}
}
One of the classes (The other two looks similar except the method "Calculate_Price"):
class Charter: AbsFlight
{
public override float Calculate_Price(float Base_Price)
{
return base.Calculate_Price(Base_Price) * 3;
}
}
Main:
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2)); //OK
Console.WriteLine(flight.ID); //Error
}
static void Main(string[] args)
{
List<IFlight> flights = new List<IFlight>();
flights.Add(new Regular());
flights.Add(new Charter());
flights.Add(new LowCost());
Main_SomeMethod(flights[0]);
}
Your current solution, in combination with some of the suggestions, will be a case of a mounted riding rider. You don't need an interface and a base class and testing for type.
You can solve your problem the way you're trying, with a base class and an interface. But it's overkill, and you have to kind of duplicate some stuff in the interface and the base class.
You can solve your problem with a simple base class and three derived classes where only Calculate_Price gets overridden. Put the common items in the base class. This is a very simple solution, easy to figure out, especially if C# and OOP is new to you.
You can also solve your problem with an interface and three classes, not derived. This has the disadvantage that you have to implement the interface in three classes. As Peter Csala points out, C# 8 has some language features that can help minimize this work, possibly making this just as simple as using only a base class and no interface. I am not too familiar with those features, so I can't judge whether it makes sense.
Then there is another option entirely. This touches on what zaitsman hinted at - that this is possibly an XY problem. Why do you want to distinguish between Regular, Charter and LowCost using classes derived from Flight/AbsFlight? Is it possible to just have an attribute that tells what price profile is used? Are there other fields and properties of a Flight that has nothing to do with the price, and yet also distinguishes flights? Perhaps just use one class.
About testing for class type. This is what we call code smell. Generally, if you test for class types a lot, then you defy the purpose of using classes and/or interfaces in the first place.
Your method should accept the type that has the properties it needs, in this case the AbsFlight class.
private static void Some_Method(AbsFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
Console.WriteLine(flight.ID); //OK
}
But let's says the method must accept any IFlight. In this case, it can't be sure it received an AbsFlight; it has to check. After the check you can just cast.
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
if (flight is AbsFlight)
{
Console.WriteLine(((AbsFlight)flight).ID); //OK
}
}
With c#7 there is an additional construct you can use, if you think it is clearer:
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
switch (flight)
{
case AbsFlight absFlight:
Console.WriteLine(absFlight.ID); //OK
break;
}
}
It seems to be that you are doing something wrong that this is your requirement.
When you use an interface and pass it as an argument you want it to be common to all the objects that implement it.
Anyway, if you do want to do it. You might do something like:
if (flight is Flight)
{
Flight yourFlight = (Flight)flight;
// Here you can use anything you need from Flight, e.g: yourFlight.ID
}
I have two function which have some common functionality (i.e. to make connection with service and close connection after calling). I made a method named "InvokeService" with parameter of Func in it.How can I get parameters of request in InvokeService? I mean I need to get the object value of request? You can clear be clear by my demo code given below:
public void Method1(){
InvokeService(()=> _service.getMathod1(request);
}
public void Method2(){
InvokeService(()=> _service.getMathod2(request);
}
public void InvokeService(Func<T> request){
//service open
//I need here a complete object of the request of Method2 and its parameters
request.Invoke();
//service close
}
If any thing ambiguous or not understandable feel free to ask me.
You may want to use the template method pattern:
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
In your case, you can have something like this:
public abstract class AbstractClass
{
protected abstract void PrimitiveOperation();
public void TemplateMethod()
{
// before common functionality
PrimitiveOperation();
// after common functionality
}
}
class ConcreteClassA : AbstractClass
{
protected override void PrimitiveOperation()
{
// your A logic
}
}
class ConcreteClassB : AbstractClass
{
protected override void PrimitiveOperation()
{
// your B logic
}
}
If you want to return something different for each concrete class or have a different parameter depending the concrete class, you can achieve that with generics. Let me know if that is the case.
It can be solve by using Reflection;
request.GetMethodInfo()
I'm working with code to implement a hardware test system, which involves communication with several benchtop instruments. When I instantiate an instance of one of these instruments, the constructor attempts to open the communication session with the instrument. If that fails, I can throw all kinds of errors, but what I'd like to do is to have the instrument object default to a virtual or simulation mode where no actual communication is done but I can still run my code.
Right now I have all instruments of one type inheriting from a base class. I've added virtual methods to the base class which perform these debugging functions, but I'm stuck on a clean way to modify the derived object at creation time to implement the base classes methods when the communication session fails.
The ideal solution would be to have the constructor (technically the new keyword) return an instance of the base class instead of the derived class, but I've done a fair amount of searching and that doesn't appear to be possible.
I could add a property to the derived class to use as a boolean flag where every method in the derived class tests against that flag and invokes the base class method if true, but I'm hoping to find a more elegant solution that doesn't require a few hundred if statements and a serious flogging of base.Stuff() calls.
I have a few dozen methods and a handful of instruments inheriting in this way so a solution that doesn't require an explicit change to every one of those overriding methods would go a long, long way.
public abstract class BaseInstrument
{
public string Address;
protected MessageBasedSession MbSession;
public virtual string Identify()
{
return "Debugging mode, fake identity";
}
}
public class SpecificInstrument : BaseInstrument
{
public SpecificInstrument(string address)
{
Address = address;
try
{
MbSession = (MessageBasedSession)ResourceManager.GetLocalManager().Open(Address);
}
catch
{
// Return an object modified in such a way that it invokes base class virtual methods
// instead of method overrides.
// Constructor has no return value (that comes from the new keyword) so I can't
// just return an instance of the base class...
}
}
public override string Identify()
{
return ActualInstrumentRead();
}
// ...
}
public class Program
{
public static void Main()
{
SpecificInstrument instr = new SpecificInstrument(ipAddress);
Console.WriteLine(instr.Identify()); // Would like to print the debug case if eg. my LAN is down
}
}
I feel like I might be missing an obvious solution to this but I've been scratching my head for hours.
You can't return a BaseInstrument from a SpecificInstrument constructor.
One alternative would be to put this logic where you create this instrument:
BaseInstrument instrument;
try {
instrument = new SpecificInstrument();
}
catch {
instrument = new BaseInstrument();
}
Hi everyone smarter than me :-) I have another application which requires generation of an abstract class, and due to testing purposes is quite difficult to debug. therefor i created a wrapper and can define my abstract classes in visual Studio now (instead of native application)
However, the native application is expecting public abstract [obj type] values with only a get; method, and if i put in a set;, the application will bomb. Is there any way to set a field using Reflection or Mock to this field, and NOT have the set method?
//simplified class
public abstract class GetEUserAndDetails : [app specific interfaces]
{
public abstract Metastorm.Runtime.Types.Text paramFullNameLike
{
get;
set; //note: If i have this here, it will fail in Metastorm
}
public System.Data.DataSet Read()
{
//do something
}
}
and in Main() it's a c# winform, i have
Mock<Metastorm.Runtime.Models.MySampleProject.GetEUserAndDetails> mockMyBO = new Mock<Metastorm.Runtime.Models.MySampleProject.GetEUserAndDetails>() { CallBase = true };
//using reflection
foreach (PropertyInfo pi in mockMyBO.Object.GetType().GetProperties())
{
//simplified again, another form getting parameters and such
pi.SetValue(mockMyBO.Object, form.myTextParam, null);
}
If I don't have the set method, the pi.SetValue() line will fail, but if i do, it will fail in the native app. (note: i'm using the same test harness to test all sorts of abstract classes that will all implement the Read() method and need to test that it is pulling the correct data back, but the parameters will be different for each class.
Sorry if my code is bad i couldn't get it to format properly, and also please bear with me if i used the wrong terms. I'm not an expert by any means, just enough to be dangerous. I am just living with leaving the set; line for the moment and manually removing it before copy/pasting into the main application, but would like to find another way to do this for when there are many params.
If I understood your scenario correctly, you actually want to test the code in the abstract class, and not mock it.
With that in mind, I think the easiest approach in this case is simply to create a subclass within your test, that will inherit from your base class, and implement whatever is necessary for you to be able to test the base class.
Such as:
public class GetUserAndDetailsImplementation : GetEUserAndDetails
{
private Metastorm.Runtime.Types.Text _paramFullNameLike;
public override Metastorm.Runtime.Types.Text paramFullNameLike
{
get { return _paramFullNameLike; }
}
public void SetParamFullNameLike(Metastorm.Runtime.Types.Text text)
{
_paramFullNameLike = text;
}
}
And you can use that class as entry point for your testing.
Now if you really want to use a mock, have you tried the following?
var mock = new Mock<GetEUserAndDetails> { CallBase = true };
mock.SetupGet(x => x.paramFullNameLike).Returns(<some value>);
In my project, I have many DLL assemblies referenced. One of those DLL's contains the bool method that I want to change. I do not have the original source for the DLL and using a Reflector to decompile a project seems impractical. All I want to do is intercept or override this method or method call so that I can change it's return value to match my own method outside of said DLL.
Any such way to do this? Thanks!
Edit:
Here is an example:
public virtual bool isOwner()
{
return false;
}
Essentially, I just want to change getOwner to return true;
If the class is public and the method is marked as virtual, then you can simply override it with this syntax:
public MyClass : TheClass
{
public override ReturnType MethodName(Arguments)
{
//class the base class implementation if needed
//base.MethodName(Arguments)
//do your own stuff and return whatever is needed
}
}
Hope this helps
EDIT: A word of caution though, this won't replace the calling code within the DLL. It will only work if you instantiate the derived class yourself and call it from your code.
Is there a general way to do what you want, built into .NET?
Yes, and no.
If you want every usage of class X' method Y to be replaced by some other code, then no, there is nothing built into .NET class system or compiler that will do this.
If you can inherit from class X, overriding method Y, and then ensure that all places where class X is used, your new class is used instead, then yes, that is the proper way to do this.
This is easily done:
public class YourFixedClass : TheProblematicClass
{
public override string YourProblematicMethod()
{
// probably call the problematic method through base.
// and fix the return value, or fix the parameters
// or don't call it at all, re-doing whatever it does
}
}
Or, if you can make a new class that implements all the same interfaces, wrapping (delegating) all the methods and properties of the original (problematic) class, then that might be doable, but this requires all actual usage of the class to go through the interfaces.
As this:
public class Wrapper : IInterface1, IInterface2
{
private readonly YourProblematicClass _C;
public Wrapper(YourProblematicClass c)
{
_C = c;
}
public string YourProblematicMetho()
{
// probably call the problematic method through _C.
// and fix the return value, or fix the parameters
// or don't call it at all, re-doing whatever it does
}
}
If, on the other hand, you don't have control of where all the code is that calls the class/method, then no, you can't do any of this.
So what else is there? Well, there is always the debugger interfaces. You can make a program that is somehow the debugger of itself, patching in the right code upon demand, but this is likely to be extraordinary difficult to get right.
In short, no, there is no way to do what you want. You need to find a different way to accomplish this.
Have you thought about changing the original assembly in the first place? I understand that you don't have the source code for it, but is that because:
You lost it
You didn't make it
In point 1, I would really work towards recreating the source code, either through a decompiler or similar, and get a new project going to fix that.
In point 2, have you thought about contacting the people that made it and asking them for help?
Uhm Ok you can do something like this:
public class MyNameClass : MyDllname.MyClassName
{
public bool isOwner()
{
return !base.isOwner();
}
}
Then you have override the method and you can use all the other methods in the DLL simply using an istance(if there aren't static) of the MyNameClass
You can use "new" modifier.
See example on http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
Or this:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new ClassA().IsEvenDayToday()); // Result: true
Console.WriteLine(new ClassB().IsEvenDayToday()); // Result: false
Console.ReadKey();
}
}
public class ClassA : ClassB
{
public new bool IsEvenDayToday()
{
return DateTime.Now.Day % 2 == 0;
}
}
public class ClassB
{
public bool IsEvenDayToday()
{
return DateTime.Now.Day % 2 != 0;
}
}