Appending to a string (created in base class) in derived classes - c#

So this is a rather specific question.
Assuming I have a set of classes, which all generate a different string. The only thing in common between these, is that they require the same "header" in the string.
I have decided to create a base class for generating the header, which they all derive from.
internal abstract class StringBase
{
public virtual string WriteString()
{
var headerString = "header";
return headerString;
}
}
Now for a derived class, which must include the header, but also add its own subsequent string.
internal class DerivedString : StringBase
{
public override string WriteString()
{
var derivedString = // How would I best add the header and append more to it?
return derivedString;
}
}
Overriding it like this would obviously overwrite whatever the base WriteString() does, so how would I make sure I get it? Could it be something like adding a non-virtual method in the base, which then calls the virtual method with the header string as a parameter?
internal abstract class StringBase
{
public void WriteHeader()
{
var headerString = "header";
WriteString(headerString);
}
public virtual string WriteString(string headerString)
{
var derivedString = headerString.Append("whateverString");
return string.empty;
}
}
internal class DerivedString : StringBase
{
public override string WriteString(string headerString)
{
var derivedString = headerString.Append("whateverString");
return derivedString;
}
}

You could use the base keyword for this, like so:
internal class DerivedString : StringBase
{
public override string WriteString(string headerString)
{
var derivedString = base.WriteString().Append("whateverString");
return derivedString;
}
}

One way to make it work is by using a private field in base class:
internal abstract class StringBase
{
private string headerString = "header";
public virtual string WriteString(String input=null)
{
return String.IsNullOrEmpty(input) ? headerString : headerString + input;
}
}
and then you can call the method from derived classes by passing in the parameter.

Related

Same interface different ctor implementaion

I have and in interface ICalibrationToolsLoader
namespace Utilities.Interfaces
{
public interface ICalibrationToolsLoader
{
string GetDefaultIspFile(string selectedSensorType = null);
IspSectionUiSettings GetIspSectionUiSettings();
List<CalibrationGroup> GetCmcGroupOrder();
}
}
and two classes implements it.
public class Ipu6CalibraitionToolsLoader : ICalibrationToolsLoader
{
private string _selectedSensorType;
public Ipu6CalibraitionToolsLoader(string selectedSensorType)
{
_selectedSensorType = selectedSensorType;
_ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile(_selectedSensorType));
InitCmcOrder();
}
public string GetDefaultIspFile(string selectedSensorType = null)
{
string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string pathSuffix = null;
switch ((IPU6SensorType)Enum.Parse(typeof(IPU6SensorType), selectedSensorType))
{
case IPU6SensorType.None:
break;
case IPU6SensorType.Bayer:
pathSuffix = "IPUs\\IPU6\\IPU6DefaultsIspFile.xml";
break;
case IPU6SensorType.MD:
pathSuffix = "IPUs\\IPU6\\IPU6MdDefaultsIspFile.xml";
break;
default:
throw new ArgumentOutOfRangeException("selectedSensorType", selectedSensorType, null);
}
if (pathSuffix != null)
{
string path = Path.Combine(location, pathSuffix);
return path;
}
throw new Exception("missing defaultIspFileXml");
}
public void InitCmcOrder()
{
_cmcCalibrationToolsOrder = new List<CalibrationGroup>
{
CalibrationGroup.GeneralDataTools,
CalibrationGroup.SensorAndModuleSettingsTools,
CalibrationGroup.LateralChromaticAberrationTool,
};
}
}
public class Ipu4CalibraitionToolsLoader : ICalibrationToolsLoader
{
public Ipu4CalibraitionToolsLoader()
{
_ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile());
InitCmcOrder();
}
public string GetDefaultIspFile(string selectedSensorType = null)
{
string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string pathSuffix = "IPUs\\Broxton\\IPU4DefaultsIspFile.xml";
string path = Path.Combine(location, pathSuffix);
return path;
}
public void InitCmcOrder()
{
_cmcCalibrationToolsOrder = new List<CalibrationGroup>
{
CalibrationGroup.GeneralDataTools,
CalibrationGroup.SensorAndModuleSettingsTools,
CalibrationGroup.LateralChromaticAberrationTool,
};
}
}
basically most of the functions are the same however, functions like the constructor and GetDefaultIsp needs to have different implementation.
I tried to use inheritance but calling a virtual function inside the constructor is a big NO NO.
Can you suggest of another way of doing so?
having 2 classes using the same interface however some methods should have different implementation?
I don't want to have another function like Init() which needs to be called after the constructor.
EDIT: Addition of the IoC implementation to solve your issue!
IoC Version
The IoC solution is, in my opinion, way more elegant but probably a little bit more complicated to maintain when you are not used to IoC.
Credits goes to plalx for suggesting it in the comments :D.
// There is no need for an interface anymore (but you can keep it of course)
public class IpuCalibrationToolsLoader
{
private string _selectedSensorType;
private string _ispSectionUiSettings;
private List<CalibrationGroup> _cmcCalibrationToolsOrder;
public IIspFileProvider Provider { get; private set; }
// Notice the internal constructor. No one will be able to create an instance of IpuCalibrationToolsLoader out of your assembly except the factory
internal IpuCalibrationToolsLoader(IIspFileProvider provider, string selectedSensorType = null)
{
this.Provider = provider;
_selectedSensorType = selectedSensorType;
_ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(provider.GetDefaultIspFile(_selectedSensorType));
this.InitCmcOrder();
}
public void InitCmcOrder()
{
_cmcCalibrationToolsOrder = new List<CalibrationGroup>
{
CalibrationGroup.GeneralDataTools,
CalibrationGroup.SensorAndModuleSettingsTools,
CalibrationGroup.LateralChromaticAberrationTool,
};
}
[..] // Since the Provider is exposed as a properties of your IpuCalibrationClassLoader, there is no need for defining the GetDefaultIspFile methods within this class
}
public interface IIspFileProvider
{
string GetDefaultIspFile(string selectedSensorType = null);
}
public class Ipu6FileProvider : IIspFileProvider
{
public string GetDefaultIspFile(string selectedSensorType = null)
{
string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string pathSuffix = null;
switch ((IPU6SensorType)Enum.Parse(typeof(IPU6SensorType), selectedSensorType))
{
case IPU6SensorType.None:
break;
case IPU6SensorType.Bayer:
pathSuffix = "IPUs\\IPU6\\IPU6DefaultsIspFile.xml";
break;
case IPU6SensorType.MD:
pathSuffix = "IPUs\\IPU6\\IPU6MdDefaultsIspFile.xml";
break;
default:
throw new ArgumentOutOfRangeException("selectedSensorType", selectedSensorType, null);
}
if (pathSuffix != null)
{
string path = Path.Combine(location, pathSuffix);
return path;
}
throw new Exception("missing defaultIspFileXml");
}
}
public class Ipu4FileProvider : IIspFileProvider
{
public string GetDefaultIspFile(string selectedSensorType = null)
{
string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string pathSuffix = "IPUs\\Broxton\\IPU4DefaultsIspFile.xml";
string path = Path.Combine(location, pathSuffix);
return path;
}
}
public static class IpuCalibrationToolsLoaderFactory
{
public static IpuCalibrationToolsLoader GetIpu4CalibrationToolsLoader()
{
return new IpuCalibrationToolsLoader(new Ipu4FileProvider());
}
public static IpuCalibrationToolsLoader GetIpu6CalibrationToolsLoader(string selectedSensorType)
{
return new IpuCalibrationToolsLoader(new Ipu6FileProvider(), selectedSensorType);
}
}
Inheritance version
Here is the version using an abstract class. An abstract class is a class you cannot instantiate. It only holds some code:
public abstract class BaseCalibrationToolsLoader : ICalibrationToolsLoader
{
public BaseCalibrationToolsLoader()
{
// put here the shared constructor code
_cmcCalibrationToolsOrder = new List<CalibrationGroup>
{
CalibrationGroup.GeneralDataTools,
CalibrationGroup.SensorAndModuleSettingsTools,
CalibrationGroup.LateralChromaticAberrationTool,
};
}
public List<CalibrationGroup> GetCmcGroupOrder()
{
// Put here the shared code among the two implementation
}
// As the implementation is different, you declare the method abstract so you only implement it in the concret classes
public abstract string GetDefaultIspFile(string selectedSensorType = null);
}
Now, you can create your concrete implementation that derived from the abstract class:
public class Ipu4CalibraitionToolsLoader : BaseCalibrationToolsLoader
{
public Ipu4CalibraitionToolsLoader ()
: base() // <- call the protected constructor
{
// put here the specific implementation constructor code
// notice that the constructor of the abstract class will **ALWAYS** be call before this code
_ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile());
}
// The GetCmcGroupOrder is already implemented, nothing to do about it
// With the sealed keyword, the method cannot be overriden in another class
public sealed override void GetDefaultIsp(string selectedSensorType = null)
{
// put here the concrete implementation for Ipu4
}
}
public class Ipu6CalibraitionToolsLoader: BaseCalibrationToolsLoader
{
public Ipu6CalibraitionToolsLoader(string selectedSensorType)
: base() // <- call the protected constructor
{
// put here the specific implementation constructor code
// notice that the constructor of the abstract class will **ALWAYS** be call before this code
_selectedSensorType = selectedSensorType;
_ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile(_selectedSensorType));
}
// The GetCmcGroupOrder is already implemented, nothing to do about it
// With the sealed keyword, the method cannot be overriden in another class
public sealed override void GetDefaultIsp(string selectedSensorType = null)
{
// put here the concrete implementation for Ipu6
}
}
As for the abstract constructor, you can define a virtual method in the abstract class and call it in the concrete implementation, in order to share a part of the code:
public abstract class BaseCalibrationToolsLoader : ICalibrationToolsLoader
{
[..]
// By using the virtual keyword, you allow your method to be overriden in the derived classes
public virtual void PartiallySharedMethod()
{
// Shared implementation
}
[..]
}
And in the concrete implementations:
public class Ipu4CalibraitionToolsLoader : BaseCalibrationToolsLoader
{
[..]
public override void PartiallySharedMethod()
{
// Unlike in the constructor, you can call the base method whenever you want.
// Some specific code can came here
base.PartiallySharedMethod();
// And other specific code can also came here
}
[..]
}
public class Ipu6CalibraitionToolsLoader: BaseCalibrationToolsLoader
{
[..]
public override void PartiallySharedMethod()
{
// Unlike in the constructor, you can call the base method whenever you want.
// Some specific code can came here
base.PartiallySharedMethod();
// And other specific code can also came here
}
[..]
}

How to perform Moq testing for abstract class in C# for virtual methods inside it?

I would like to perform testing for below abstract Streaming class which has two virtual methods that are overridden in the Asset class in same project. Here the SerializeBinary() method converts an object into binary streams and DeserializeFromBinary() method does the opposite of SerializeBinary().
How to write test class for comparing both using Moq?
I go through from here:
This is part of my code:
Streaming class:
public abstract class Streaming
{
private static int _streamingIDExponent = 41;
public const string MonthLookup = "ABCDEFGHIJK";
public const string ExpiryStringFormat = "ddMMMyyyy";
public const double DefaultTicksPerPoint = 3;
private long _StreamingID;
private int _minQty = DefaultMinimumQty;
public virtual void SerializeBinary(BinaryStreamWriter binaryStreamWriter)
{
binaryStreamWriter.Write(_StreamingID);
binaryStreamWriter.Write(_ex_StreamingID);
binaryStreamWriter.Write(_minQty);
binaryStreamWriter.Write(_extendedProperties.Count);
foreach (KeyValuePair<StreamingPropertyName, StreamingProperty> dictionaryEntry in _extendedProperties)
{
dictionaryEntry.Value.SerializeBinary(binaryStreamWriter);
}
}
public virtual bool DeserializeFromBinary(BinaryStreamReader binaryStreamReader, out string errorString)
{
errorString = string.Empty;
try
{
_StreamingID = binaryStreamReader.ReadInt64();
_exStreamingID = binaryStreamReader.ReadInt64();
_minQty = binaryStreamReader.ReadInt32();
}
catch (Exception oEx)
{
errorString = oEx.Message;
}
return string.IsNullOrEmpty(errorString);
}
Asset class:
public class Asset : Streaming
{
public override void SerializeBinary(BinaryStreamWriter binaryStreamWriter)
{
base.SerializeBinary(binaryStreamWriter);
}
public override bool DeserializeFromBinary(BinaryStreamReader binaryStreamReader, out string errorString)
{
if (!base.DeserializeFromBinary(binaryStreamReader, out errorString))
return false;
try
{
return true;
}
catch (Exception oEx)
{
errorString = oEx.Message;
return false;
}
}
}
you can create a new Mock of your Streaming class like this:
var streamingMock = new Mock<Streaming> { CallBase = true };
The call base is important because it will then execute the implemented code in your concrete class.
Then you can call the methods via the Object property:
streamingMock.Object.SerializeBinary(...);
Hope this helps
There's no good way to test the interaction between Asset and Streaming with Moq in your current implementation. However, if you're willing to change the implementation of the classes just a bit, you can get it done. Basically, you'll want to move the logic of the Streaming class's methods into new methods, and you can then mock those.
public abstract class Streaming
{
public virtual void SerializeBinaryCore(BinaryStreamWriter writer)
{
// put the logic from your original SerializeBinary method here...
}
public virtual bool DeserializeFromBinaryCore(BinaryStreamReader reader, out string errorMessage)
{
// put the logic from your original DeserializeFromBinary method here...
}
public abstract void SerializeBinary(BinaryStreamWriter writer);
public abstract bool DeserializeFromBinary(BinaryStreamReader reader, out string errorMessage);
}
And then tweak your Asset class as follows:
public class Asset : Streaming
{
public override void SerializeBinary(BinaryStreamWriter writer)
{
SerializeBinaryCore(writer);
}
public override void DeserializeFromBinary(BinaryStreamReader reader, out string errorMessage)
{
var result = DeserializeFromBinaryCore(reader, out errorMessage);
// put the rest of your Asset deserialization logic here...
}
}
In your test, you need to create a Mock<Asset> { CallBase = true }, and then create setups for the SerializeBinaryCore and DeserializeFromBinaryCore methods.

Put different subclasses from the same base class into a list C#

I want to add different sub classes which extends from the same base class into a List.
So this is the base class:
public class InteractionRequirement {
protected int requirementNumber;
public int RequirementNumber{
get{ return requirementNumber;}
set{ requirementNumber = value;}
}
}
And these are the subclasses:
public class ObjectInteraction : InteractionRequirement {
protected string objectName;
--getter and setter here--
}
public class CharacterInteraction: InteractionRequirement {
protected string characterName;
--getter and setter here--
}
public class AssetInteraction: InteractionRequirement {
protected string assetName;
--getter and setter here--
}
And I added them in one list:
List<InteractionRequirement> interactionRequirements = new List<InteractionRequirement>();
ObjectInteraction objectInteraction = new ObjectInteraction();
CharacterInteraction characterInteraction = new CharacterInteraction();
AssetInteraction assetInteraction = new AssetInteraction();
interactionRequirements.Add(objectInteraction);
interactionRequirements.Add(characterInteraction);
interactionRequirements.Add(assetInteraction);
But I can't seem to retrieve attribute values from the sub classes, there's an error.
string oName = interactionRequirement[0].ObjectName;
string cName = interactionRequirement[1].CharacterName;
string aName = interactionRequirement[2].AssetName;
That's because the interactionRequirements collection is of type InteractionRequirement not of the derived type (ObjectInteraction, CharacterIteraction or AssetInteraction).
Therefore, you'll need a cast.
string oName = ((ObjectInteraction)interactionRequirement[0]).ObjectName;
You can also use as and check if the cast was successful.
var objectInteraction = interactionRequirement[0] as ObjectInteraction;
if (objectInteraction != null)
{
string oName = objectInteraction.ObjectName;
}
http://ideone.com/4giIL4
As an additional note, you may need to change the protection level of ObjectName to public so you can access it in the appropriate context (Outside of the class and derived classes).

How to call a method in another class from a generic method?

Why doesn't the line marked with //Dont work in the bottom of the code compile?
I want to reuse the WriteMessage method with different Classes, I try to use generics, but I'm not sure how to use it.
class ClassOne
{
public string MethodOne()
{
return ("ClassOne");
}
public string MethodTwo()
{
return ("ClassOne -MethodTwo ");
}
}
class ClassTwo
{
public string MethodOne()
{
return ("ClassTwo");
}
public string MethodTwo()
{
return ("ClassOne -MethodTwo ");
}
}
class Program
{
private static void Main()
{
var objectOne = new ClassOne();
WriteMessage(objectOne);
var objectTwo = new ClassTwo();
WriteMessage(objectTwo);
Console.ReadKey();
}
public static void WriteMessage<T>(T objectA)
{
var text = objectA.MethodTwo(); //Dont Work
Console.WriteLine("Text:{0}", text);
}
}
Try implementing a interface :
Example :
public interface IHasTwoMethods
{
string MethodOne()
string MethodTwo()
}
Implement this inteface on your classes :
class ClassOne : IHasTwoMethods
class ClassTwo : IHasTwoMethods
Then in your generic method do like this :
public static void WriteMessage<T>(T objectA) where T : IHasTwoMethods
{
var text = objectA.MethodTwo(); //Will work
Console.WriteLine("Text:{0}", text);
}
You can read more about interfaces here : http://msdn.microsoft.com/en-us/library/87d83y5b.aspx
This doesn't compile because as far as the compiler is concerned objectA is just an Object.
To get this to work, you need to use a generic type constraint:
public interface MyInterface
{
string MethodTwo();
}
public class A : MyInterface
{
...
}
public class B : MyInterface
{
...
}
public static void WriteMessage<T>(T objectA) where T: MyInterface
{
var text = objectA.MethodTwo(); //Will Work!
Console.WriteLine("Text:{0}", text);
}
MSDN : Constraints on Type Parameters
Since you're passing in a generically-typed object with T, the compiler doesn't know what class you're using--for all it knows, it could be an int or an Application or anything.
What you probably want is to have ClassOne and ClassTwo inherit from another class that has an abstract MethodTwo class that both implement. Something like...
abstract class SuperClass
{
public abstract string MethodOne();
}
class ClassOne : SuperClass
{
public override string MethodOne()
{
return ("ClassOne");
}
}
then in Main:
public static void WriteMessage<T>(T objectA) where T : SuperClass
{
var text = objectA.MethodOne();
Console.WriteLine("Text:{0}", text);
}
Read up on C# inheritance here: http://msdn.microsoft.com/en-us/library/ms173149.aspx

No static in generic. But how to achieve this?

Please check the following section of code (Simplified version)
my concern is in the ReadPath class where I need to call the GetPath() of the type i am using. How can I achieve this?
public interface IPath
{
string GetPath();
}
public class classA: IPath
{
string GetPath()
{
return "C:\";
}
}
public class classB: IPath
{
string GetPath()
{
return "D:\";
}
}
public class ReadPath<T> where T : IPath
{
public List<T> ReadType()
{
// How to call GetPath() associated with the context type.
}
}
public interface IPath
{
string GetPath();
}
public class classA : IPath
{
public string GetPath()
{
return #"C:\";
}
}
public class classB : IPath
{
public string GetPath()
{
return #"D:\";
}
}
public class ReadPath<T> where T : IPath, new()
{
private IPath iPath;
public List<T> ReadType()
{
iPath = new T();
iPath.GetPath();
//return some list of type T
}
}
Interfaces are instance based. So if you want to do that, pass in an instance and work with that.
However, there is a concept that is type-based: attributes:
[TypePath(#"C:\")]
public class classA
{
}
[TypePath(#"D:\")]
public class classB
{
}
public class ReadPath<T>
{
public static List<T> ReadType()
{
var attrib = (TypePathAttribute)Attribute.GetCustomAttribute(
typeof(T), typeof(TypePathAttribute));
var path = attrib.Path;
...
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
| AttributeTargets.Interface | AttributeTargets.Enum,
AllowMultiple = false, Inherited = false)]
public class TypePathAttribute : Attribute
{
public string Path { get; private set; }
public TypePathAttribute(string path) { Path = path; }
}
Another solution is instance member, but you should change a declaration of generic a little bit:
public class ReadPath<T> where T : IPath, new() //default ctor presence
{
T mem = new T();
public string ReadType()
{
return mem.GetPath();
}
}
Not that I changed returned type as it's not clear how you gonna fit return type string with List<T>
You are confusing between few different aspects of .net/c# programing.
Static methods (which you dont even have here) cannot be defined via interfaces, so if you're interested in using static methods, the interface wotn help you, and you could execute such method in a generic way only by means of reflection.
Your code is abit not clear, hard to understand why your readtype method returns a list, and how are you supposed to fill up this list.

Categories

Resources