Static override / abstract methods - Any good workaround? - c#

I have an abstract base configuration class and two implementations:
public abstract class BaseConfiguration
{
}
public class LoginConfiguration : BaseConfiguration
{
public LoginConfiguration()
{
}
public string Name { get; set; }
public string Password { get; set; }
}
public class TestConfiguration : BaseConfiguration
{
public TestConfiguration()
{
}
}
The problem I am facing:
Every specific class type has a explicit filename it points to. This means LoginConfiguration has a filename called "login.xml" and TestConfiguration points to "test.xml".
The filename I would like to use for deserialization later on:
static void Main(string[] args)
{
LoginConfiguration login = ReadFromFile<LoginConfiguration>();
Console.ReadLine();
}
private static TConfig ReadFromFile<TConfig>() where TConfig : BaseConfiguration
{
//Something like this needs to be done here:
string filename = TConfig.GetFilename();
//Deserialize file and return object
return Deserialize<TConfig>(filename);
}
But I know that you can neither have static overides nor static abstract methods.
What I am currently doing is using the base class to instantiate a new object and read the filename from the instance, but thats very hacky.
public abstract class BaseConfiguration
{
protected BaseConfiguration(string fileName)
{
Filename = fileName;
}
public string Filename { get; private set; }
public static string GetFilename<TConfig>() where TConfig : BaseConfiguration, new()
{
return new TConfig().Filename;
}
}
//The calling method:
private static TConfig ReadFromFile<TConfig>() where TConfig : BaseConfiguration, new()
{
string filename = BaseConfiguration.GetFilename<TConfig>();
//Deserialize file and return object
return Deserialize<TConfig>(filename);
}
My question is now:
Do you have any idea, how I can design it better? Do you have a better Approach?
And wouldn't static abstract methods in C# make sense at this kind of issue?
Thanks in advance!

If you don't mind a bit of reflection, you could add an attribute to provide the file name:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ConfigFileAttribute : Attribute
{
...
}
[ConfigFile("login.xml")]
public class LoginConfiguration
{
...
}
Since you already have the type (TConfig), you can access the attribute using:
var configAttributes = typeof(TConfig).GetCustomAttributes(typeof(ConfigFileAttribute), false);
Of course this does mean that forgetting the attribute would make the read fail.
This is not the "best" solution, but I personally prefer the separate administration of a filename, where the class itself has no interest in it.

The reason for your weird design is because your XXXConfiguration class breaks Single Responsibility Principle, it has a property named filename, to tell the caller where its data comes from, and other properties to save the loaded data. IMO the XXXConfiguration class should only contain the data, there is no information of its data source.
abstract class BaseConfiguration
{
public string SharedConfigProperty { get; set; }
}
class LoginConfiguration : BaseConfiguration
{
public string LoginConfigProperty { get; set; }
}
class TestConfiguration : BaseConfiguration
{
public string TestConfigProperty { get; set; }
}
In your original design, LoginConfiguration can only have one data-source, it will be a nightmare if you have login-dev.xml login-qa.xml in the future. Put the load function of configurations in another class is better:
class ConfigurationFactory
{
public static TConfig FromFile<TConfig>() where TConfig : BaseConfiguration
{
//you should have a TConfig-fileName mapping
//e.g. a Dictionary<Type, string>
//Type is typeof(TConfig) and string is the filename
}
public static TConfig FromDataBase<TConfig>() where TConfig : BaseConfiguration
{
//as I said, the original design has a lot of restricts
//what if they change the storage from file to data base?
//you need to change every derived class, renaming FileName to DataBaseTableName?
}
}

Yeah I sometimes wish for the ability to specify a contract 'if you extend this class then you need to provide a static method with this signature', but unfortunately that doesn't exist.
It's not that much neater, but I would probably make a static map of the filenames like this:
public abstract class BaseConfiguration
{
static BaseConfiguration()
{
Filenames = new Dictionary<Type, string>
{
{ typeof(LoginConfiguration), "login.xml" },
{ typeof(TestConfiguration), "test.xml" },
};
}
private static Dictionary<Type, string> Filenames { get; }
public static string GetFilename<TConfig>() where TConfig : BaseConfiguration
{
return Filenames[typeof(TConfig)];
}
}
The advantages being that you have all the filenames in one place and that you don't need to allocate an instance to get the filename.

Related

Overrideable property that can be accessed both by instance and by class

I have an inheritance tree with a bunch of different classes. Each of these classes has some static properties that I need acces to from time to time. Sometimes I need the property of a particular class, and sometimes I need the property of the specific class some polymorphic instance turns out to be.
This would be easy in, say, Java (I think). Just make a bunch of static fields (can these be overriden? I'm not sure). But in C#, non-static fields can ONLY be accessed via an instance (naturally), and static fields can ONLY be accessed via their corresponding class (unnaturally).
And, you can't "overload" by, er, staticity. If a class has a static and a non static Foo, doing instance.Foo fails because it is unclear to the compiler which Foo you're referring to even though it's impossible you're referring to the static one since it's disallowed.
Ok, I'll provide some code. Say I have this:
class Base
{
public static readonly string Property = "Base";
}
class Child1 : Base
{
public static readonly new string Property = "Child 1";
}
class Child2 : Base
{
public static readonly new string Property = "Child 2";
}
And then, somewhere:
public void SomeMethod(Base instance)
{
System.Console.WriteLine(instance.Property); // This doesn't work.
}
And somewhere else:
public void SomeOtherMethod()
{
System.Console.WriteLine(Child2.Property);
}
I want something like that, that actually works.
As Peter Duniho said, this can be done with reflection.
For example, these can be defined within the base class:
public const string Property = "Base";
public virtual string InstanceProperty
{
get
{
return (string)this.GetType()
.GetField("Property", BindingFlags.Public | BindingFlags.Static)
.GetValue(null);
}
}
And then each derived class just has to redefine Property using the new keyword.
I think the best you'll do in C# is something like this:
public class BaseClass
{
public virtual string InstanceProperty
{
get { return StaticProperty; }
}
public static string StaticProperty
{
get { return "BaseClass"; }
}
}
public class Derived1Base : BaseClass
{
public override string InstanceProperty
{
get { return StaticProperty; }
}
public new static string StaticProperty
{
get { return "Derived1Base"; }
}
}
public class Derived1Derived1Base : Derived1Base
{
}
public class Derived2Base : BaseClass
{
public override string InstanceProperty
{
get { return StaticProperty; }
}
public new static string StaticProperty
{
get { return "Derived2Base"; }
}
}

Base Class Used With Types, Possible to Assign Generically?

Assuming the following code:
public class Shared
{
public string String1 { get; set; }
}
public class ImplementedOne : Shared{}
public class ImplementedTwo : Shared{}
public T SetBaseProperties<T>(Shared shared)
{
// go through and assign, return type ImplementedOne or ImplementedTwo
}
I have two objects inheriting from Shared, ImplementedOne and ImplementedTwo. Each of these uses the property String1, however it can vary between the object instances. Since both of them inherit the base class, can I have a generic method that assigns these common properties?
If you are looking for a place to initialize the String1 property it should be in the base class constructor
public class Shared
{
public string String1 { get; set; }
public Shared(string str)
{
String1 = str;
}
}
And than just
public class ImplementedOne : Shared
{
public ImplementedOne() : base("your string")
{
}
}
I suggest either implementing a method in Shared to set its properties:
public class Shared
{
public void SetProperties( Shared shared )
{
this.String1 = shared.String1;
}
}
Or creating a copy constructor for Shared that is called by derived classes' constructors that accept an instance of Shared (this is my preferred method):
public class Shared
{
public Shared( Shared source )
{
this.String1 = source.String1;
}
}
public class ImplementedOne : Shared
{
public ImplementedOne( Shared source ) : base( source )
{
}
}
Update:
I may have misunderstood your question - if you're asking how to assign a single property to the same value for each instance of derived type, I would make the property virtual and implement on a per class basis:
public class Shared
{
public virtual string String1 { get { return "Shared's string"; } }
}
public class ImplementedOne : Shared
{
public override string String1 { get { return "ImplementedOne's string"; } }
}
public class ImplementedTwo : Shared
{
public override string String1 { get { return "ImplementedTwo's string"; } }
}
I think you are missing the point about generics...
In your particular case you just need a method in the Shared class that sets the property String1, String2...
public class Shared
{
public string String1 { get; set; }
public SetBaseProperties()
{
// go through and assign, return type ImplementedOne or ImplementedTwo
}
}
which you can use on either ImplementationX class,
var implementation1 = new Implementation1();
implementation1.SetBaseProperties();
Although, of course, this is something you would put in a construtor,
public class Shared
{
public Shared()
{
this.SetBaseProperties();
}
public string String1 { get; set; }
public SetBaseProperties()
{
// go through and assign, return type ImplementedOne or ImplementedTwo
}
}
If you really want to use a generic method to modify the types, you can use a generic constraint.
public T SetBaseProperties<T>(T object) where T : Shared
{
object.String1 = "value";
return object;
}
But it seems overkill for what you want. I would just go with what Tomek suggested.

Requiring interface implementations to have a static Parse method

I've got a minimal interface, and will be dealing with a collection of objects whose classes implement this interface. The collection (along with its associated functionality) doesn't care about any of the details of these objects beyond their name, the ability to convert them to XML, and the ability to parse them from XML.
Future implementations of the interface will do a lot more with the elements of the collection, and will obviously implement their own Parse and ToXml methods (which will be used by the collection to parse these items appropriately when encountered).
Unfortunately, I am unable to list a static Parse method in the interface (I've read these three questions). It doesn't make sense to me to have a Parse method require an instance. Is there any way to require that all implementations of the interface have a static Parse method?
public interface IFoo
{
string Name { get; }
string ToXml();
static IFoo Parse(string xml); // Not allowed - any alternatives?
}
You can't do that. And static methods aren't polymorphic anyway, so it wouldn't make too much sense.
What you want here is some kind of factory pattern.
Assuming Parse takes a string and turns it into a fully-populated object, how about a Hydrate method instead, like:
interface IFoo {
string Name { get; set; }
int Age { get; set; }
void Hydrate(string xml);
}
class Foo : IFoo {
public string Name { get; set; }
public int Age { get; set; }
public void Hydrate(string xml) {
var xmlReader = ...etc...;
Name = xmlReader.Read(...whatever...);
...etc...;
Age = xmlReader.Read(...whatever...);
}
}
void Main() {
IFoo f = new Foo();
f.Hydrate(someXml);
}
Or Fluent it up a bit:
public IFoo Hydrate(string xml) {
// do the same stuff
return this;
}
void Main() {
IFoo f = new Foo().Hydrate(someXml);
}
The only alternative that comes to my mind is to use an abstract class instead of an interface here. However you won't be able to override static method's behaviour in child classes anyway.
You can achieve somewhat similar behaviour using Factory pattern and requiring classes implementing IFoo to have a reference to that Factory (which can be injected in them via constructor injection):
public interface IFoo
{
string Name { get; }
string ToXml();
IFooFactory FooFactory { get; }
}
public interface IFooFactory
{
IFoo Parse(string xml);
}
I would extract all serialization-related methods into a different interface. Please consider the following example:
public interface IFoo
{
string Name { get; }
IFooSerializer GetSerializer(string format);
}
public enum FooSerializerFormat { Xml, Json };
public interface IFooSerializer
{
string Serialize(IFoo foo);
IFoo Deserialize(string xml);
}
public class Foo : IFoo
{
public string Name { get; }
public IFooSerializer GetSerializer(FooSerializerFormat format)
{
case FooSerializerFormat.Xml:
return new FooXmlSerializer();
case FooSerializerFormat.Json:
return new FooJsonSerializer();
}
}
public class FooXmlSerializer : IFooSerializer { /* Code omitted. */ }
public class FooJsonSerializer : IFooSerializer { /* Code omitted. */ }
Maybe this way?
public interface IFoo
{
string Name { get; }
string ToXml();
IFoo Parse(string xml);
}
public abstract class AFoo : IFoo
{
public string Name { get; set; }
public string ToXml() { };
public IFoo Parse(string xml) { return AFoo.StaticParse(xml); };
public static IFoo StaticParse(string xml) { }; // implement one here
}
Even if the above could be a solution I would encourage you to use the abstact factory and/or template method instead. See Template Method Pattern instead. Another Option might be the usage of an Extension method if you wan't to share it among several implementations.
Broadly speaking, I have been known (on occasion) to use Extension methods for stuff like this:
public interface IFoo
{
string Name {get;}
string ToXml();
}
public class Foo : IFoo
{
public Foo(string name)
{
Name = name;
}
public string Name {get; private set;}
public string ToXml()
{
return "<derp/>";
}
}
So that's the instance stuff, let's handle the "static" bit:
public static class FooExts
{
public static IFoo Parse(this string xml)
{
return new Foo("derp");
}
}
And a test:
void Main()
{
var aFoo = "some xml".Parse();
Console.WriteLine(aFoo.ToXml());
}
As #Jim mentions, there is the case where you don't want a Foo back, in which case you might use something like:
public static T Parse<T>(
this string xml,
Func<string, IFoo> useMeUseMe = null)
where T:IFoo
{
if(useMeUseMe == null)
useMeUseMe = (x => new Foo(x));
return (T)useMeUseMe("derp");
}
Alas, we must now tell the method what we want when we deviate from the "norm":
var aFoo = "some xml".Parse<Foo>();
Console.WriteLine(aFoo.ToXml());
var aBar = "some xml".Parse<Bar>(s => new Bar(s));
Console.WriteLine(aBar.ToXml());

How can I wrap static properties of a base class so that they return a sub class object?

Say I have code out there like this:
public class Base // I cannot change this class
{
public string Something { get; private set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
// How can I wrap the PreSets here so that they return SubClass objects?
// Something like this:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
}
}
}
What makes this complicated is the Something property. It has a private setter. So I can't set it in the subclass. The only way it can be set is is via the preset properties.
Is there a way to wrap the StaticPreSet property in my SubClass so that it will return an object of type SubClass?
// I cannot change this base class.
Given that you can't change the base class, there is no way to cause it to change behavior (ie: return a different class at runtime).
If you could influence the design of the base class static methods, you could redesign it in a way to be flexible enough to provide this functionality. However, without changing it, this won't work.
Edit in response to edit:
You could create a new static method that does what you are showing, like so:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
Base baseInstance = Base.StaticPreSet;
SubClass sc = new SubClass(baseInstance); // Create a new instance from your base class
return sc;
}
}
However, this provides a completely new, unrelated property - you'd have to access it via SubClass.MyWrappedPreset, not the Base class.
Static fields in a class "have nothing to do with it".
Basically, except access to private static fields, id doesn't matter in which class you put them - they behave the same.
If you inherit a class, and you declare another static field with the same name of a static field on the base class, you will simply 'hide' it. Example for you:
using System;
public class Base // I cannot change this class
{
public string Something { get; set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
public static SubClass StaticPreSet2
{
get { return new SubClass { Something = "inherited", Otherthing=""}; }
}
}
public class Test
{
public static void Main()
{
Console.WriteLine(SubClass.StaticPreSet2.Something);
}
}
Will write "inherited".

IDescription interface using generics and extension methods

I am trying to implement an IDescription Interface. Basic purpose of this interface is that I have many different classes that have a list of multilingual descriptions and I want the the basic AddDescription EditDescription and some other basic behaviours to be defined by the interface and not implemented by the classes individually that inherits the interface. I am trying to assign the behavior to the interface using extension methods.
I have some road blocks such as how do I access the descriptions collection of the entity that I am passing on to the IDescription interface (entity.Descriptions.Add)?
I am very new to generics, extension methods, anonymous types etc so please bear with me with my misunderstandings of how these are used. Will appreciate if you can help me correct the below code. I wrote it to give the idea of what I am trying to achieve, it obviously fundamental errors in it. Thanks
public class Company : IDescription<Company, CompanyDescription>
{
public IList<CompanyDescription> Desriptions { get; set; }
}
public class Location : IDescription<Location, LocationDescription>
{
public IList<LocationDescription> Desriptions { get; set; }
}
public interface IDescription<eT, dT>
{
void AddDescription(eT, string text);
void EditDescription(eT, dT, string text);
}
public static DescriptionInterfaceExtensions
{
public static void AddDescription(this IDescription<eT, dT> description, eT entity, string text)
{
dT newDescription = new dT(text);
entity.Descriptions.Add(newDescription);
}
}
Another possible rewrite that should work is to remove the Add/Edit methods from the interface and simply provide the required IList in the interface. Then, for ease of use, you can use the extension methods to make it easier.
I'm not saying this example is a great use of generics or extension methods, but it will work:
public class CompanyDescription : IDescription { public string Text { get; set; } }
public class LocationDescription : IDescription { public string Text { get; set; } }
public class Company : IHaveDescriptions<CompanyDescription>
{
public IList<CompanyDescription> Desriptions { get; set; }
}
public class Location : IHaveDescriptions<LocationDescription>
{
public IList<LocationDescription> Desriptions { get; set; }
}
public interface IDescription
{
string Text { get; set; }
}
public interface IHaveDescriptions<T>
where T : class, IDescription, new()
{
IList<T> Desriptions { get; set; }
}
public static class DescriptionInterfaceExtensions
{
public static void AddDescription<T>(this IHaveDescriptions<T> entity, string text)
where T : class, IDescription, new()
{
T newDescription = new T();
newDescription.Text = text;
entity.Desriptions.Add(newDescription);
}
public static void EditDescription<T>(this IHaveDescriptions<T> entity, T original, string text)
where T : class, IDescription, new()
{
T newDescription = new T();
newDescription.Text = text;
entity.Desriptions.Remove(original);
entity.Desriptions.Add(newDescription);
}
}
I your example it seems the contract is that objects that have a description store a list of descriptions. So, to avoid having to declare Add and Remove methods in the classes directly, you could do something like this:
Interfaces
public interface IDescription<T>
{
}
public interface IHasDescription<THasDescription, TDescription>
where THasDescription : IHasDescription<THasDescription, TDescription>
where TDescription : IDescription<THasDescription>
{
IList<TDescription> Descriptions { get; }
}
Concrete implementations
public class CompanyDescription : IDescription<Company>
{
}
public class Company : IHasDescription<Company, CompanyDescription>
{
private readonly IList<CompanyDescription> descriptions;
public IList<CompanyDescription> Descriptions
{
get { return this.descriptions; }
}
}
Extension methods
public static class DescriptionExtensions
{
public static void AddDescription<THasDescription, TDescription>(
this THasDescription subject,
TDescription description)
where THasDescription : IHasDescription<THasDescription, TDescription>
where TDescription : IDescription<THasDescription>
{
subject.Descriptions.Add(description);
}
}
But I don't think it's worth to do this just to have
mycompany.AddDescription(mydescription);
instead of
mycompany.Descriptions.Add(mydescription);
You can't add interface implementations to classes using extension methods, although that seems to be what you are trying to do.
The purpose of extension methods is to add behavior to existing types (classes or interfaces).
The problem with your code is that you declare that Company and Location should implement the IDescription interface; yet they don't. They have no AddDescription or EditDescription methods, so that's not going to work.
Why don't you instead define a concrete generic Description class and attach that class to Company and Location?

Categories