Hey, I'd like to know if what I'm trying to do is even possible? Comments in code should give and idea what I'm trying to achive :)
interface ITest<T> {
T t { get; }
bool DoTest();
}
public abstract class Test<T> : ITest<T> {
public Test (T nt) {
this.t = nt;
}
public Test () {
}
public T t {
get;
private set;
}
public abstract bool DoTest ();
}
public class STest : Test<string> {
public override bool DoTest () {
return true;
}
}
public class ITest : Test<int> {
public override bool DoTest () {
return true;
}
}
public class TestTest {
// I don't want to specify type here, I'd like TestTest to be able to have
// either a ITest or a STest. But for this class it should not matter.
// I just want to use DoTest() later on. No matter what
// specialication of Test this is.
Test myTest;
}
This might be a design problem, and I'd be willing to reconsider that if it is :)
I would suggest extracting the DoTest method to a super-interface, like this:
interface ITestable
{
bool DoTest();
}
interface ITest<T> : ITestable
{
T t { get; }
}
public class TestTest
{
ITestable myTest;
}
On an unrelated note, it is not recommended for class-names to begin with 'I' and for properties to begin with lower-case characters.
Place the DoTest() method in a non-generic ITest interface. Also, I would recommend making the ITest interface have a non-generic version of t. This is a quite common approach seen with interfaces like IEnumerable and IEnumerable<T>. The advantage is the non-generic version doesn't get less-capable and can hence can be fully leveraged in places where no actual type parameter can be supplied.
interface ITest
{
object t { get; }
bool DoTest();
}
interface ITest<T> : ITest
{
T t { get; }
}
Thanks to explicit implementation the unwanted non-generic or generic version (depending on the actual situation) can be hidden:
class STest : ITest<S>
{
public string t { get; private set; }
string ITest.t { get { return t; } }
public bool DoTest { ... }
}
Related
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
I have this setup, and it didn't work as I expected. It seems to me that a generic T in a base class is not the same as the generic T in its sub-class.
namespace StackOverflowQuestion
{
public class Poco1
{
public string Data { get; set; }
}
public class Poco2 : Poco1
{
public string ExtraData { get; set; }
}
public class Poco3 : Poco2
{
public string EvenMoreData { get; set; }
}
public class Base<T> where T: Poco1
{
public virtual void Method(T parameter)
{
// Do something even more general with Data...
parameter.Data = "Test";
}
}
public class FirstLevel<T> : Base<Poco2> where T:Poco2
{
public override void Method(Poco2 parameter)
{
// Do something general with ExtraData...
base.Method(parameter);
}
}
public class SecondLevel<T> : FirstLevel<Poco3> where T: Poco3
{
public override void Method(Poco2 parameter) // <-- Why not Poco3?
{
// Do something with EvenMoreData...
base.Method(parameter);
}
}
}
What I actually expected was that the Method override in type SecondLevel<T> should say Poco3 and not Poco2. Especially as I put a constraint on T to be of type Poco3.
Is it possible to achieve this in another way? It seems to me that the generic T can't be "overridden" the way I wanted. I suspect T in Base<T> is not the same as T in FirstLevel<T> and that T in FirstLevel<T> is not the same as T in SecondLevel<T>?
If SecondLevel<T> inherits from Base<T> then I get Poco3 in the Method override, but not when I inherit from FirstLevel<T>.
I can live with this issue, but then I need to cast the poco parameter type in Level-type sub-classes (from level 2 and up). In my opinion, that should be unnecessary as long as I specify the constraint. But, of course, there might be a good reason for this behavior that I don't see at the moment.
Rather than specifying the POCO type in each overridden method signature you can instead use the T type parameter.
T is already constrained to the POCO type you want so it should behave exactly as you want.
Oh, and I'd do the same with the type you're passing to the base class as well.
e.g.
public class FirstLevel<T> : Base<T> where T:Poco2
{
public override void Method(T parameter)
{
// Do something general with ExtraData...
base.Method(parameter);
}
}
public class SecondLevel<T> : FirstLevel<T> where T: Poco3
{
public override void Method(T parameter)
{
// Do something with EvenMoreData...
base.Method(parameter);
}
}
I have an interface for a base class, and every class that inherits from the base class should have an identifying field which tells the application what kind of object it is.
I wanted to use this property in two different ways:
Without creating an instance of the object
if (someValue == TestA.Id)
return new TestA();
elseif (someValue == TestB.Id)
return new TestB();
And as a property of the interface
void DoSomething(ITest testObject)
{
SomeValue = testObject.Id;
}
Is there an easy way to define the Id field in the interface, but still have it available to use without creating an instance of the class?
Right now I am using the following code. I could add a read-only Id property to the interface which returns the const string, however I was hoping there was a simpler way that I'm just not aware of.
public interface ITest
{
}
public class TestA : ITest
{
public const string Id = "A";
}
In short - no.
In order to be able to do this, you'd need to be able to specify this as a instance property on the interface (and implement it in the instance), and as a static property on the type.
The compiler won't let you do this.
You can put it in the interface, and also have it as a static property. Something like:
interface IInterface { Id { get; } }
class Class : IInterface
{
public static Id { get { return 1; } }
public Id { get { return Class.Id; } }
}
I've faced a similar problem, Rachel, and I've always (unfortunately) resorted to having that factory code rely on reflection to get a "TypeID" public static property on each concrete type... thus making an additional aspect of the contractual interface, but not having it in the C# interface code.
You could do it this way.
public interface ITest
{
SomeValue Id{ get;}
}
public class TestA : ITest
{
public SomeValue Id
{
get {return TestA.StaicId; }
}
public static SomeValue StaticId
{
get {return "This is TestA";}
}
}
if (someValue == TestA.StaticId)
return new TestA();
How about using attributes? Here's a small example of what can be done:
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class IdAttribute : Attribute
{
public IdAttribute(string id)
{
this.Id = id;
}
public string Id { get; set; }
}
public interface IMyInterface
{
}
public abstract class BaseClass : IMyInterface
{
public static string GetId<T>() where T : IMyInterface
{
return ((IdAttribute)typeof(T).GetCustomAttributes(typeof(IdAttribute), true)[0]).Id;
}
}
[Id("A")]
public class ImplA : BaseClass
{
}
[Id("B")]
public class ImplB : BaseClass
{
}
internal class Program
{
private static void Main(string[] args)
{
var val1 = BaseClass.GetId<ImplA>();
var val2 = BaseClass.GetId<ImplB>();
Console.ReadKey();
}
}
My example is a situation where the interfaces that inherit of the base interface need to add post conditions that are a result of their additional fields - the example occured when i decided to have an IInitialise interface as interfaces that inherit from this invariably want a pre/post condition added to the Initialise method.
I can see that the problem is due to the abstract implementations having no way to avoid each other (either due to interception or the rewriter).
[ContractClass(typeof(IInitialiseContract))]
public interface IInitialise
{
bool IsInitialised { get; }
void Initialise();
}
[ContractClassFor(typeof(IInitialise))]
public abstract class IInitialiseContract : IInitialise
{
public bool IsInitialised
{
get { return default(bool); }
}
public void Initialise()
{
Contract.Ensures(IsInitialised == true);
}
}
then later I end up with the following interface
[ContractClass(typeof(IEnginecontract))]
public interface IEngine : IInitialise
{
ICommandManager CommandManager { get; }
IDictionary<int, IEntity> World { get; }
}
[ContractClassFor(typeof(IEngine))]
public abstract class IEnginecontract : IEngine
{
public ICommandManager CommandManager
{
get
{
Contract.Ensures(Contract.Result<ICommandManager>() != null);
return default(ICommandManager);
}
}
public IDictionary<int, IEntity> World
{
get
{
Contract.Ensures(Contract.Result<IDictionary<int, IEntity>>() != null);
return default(IDictionary<int, IEntity>);
}
}
public bool IsInitialised
{
get { return default(bool); }
}
public void Initialise()
{
// I would like to put my pre and post conditions here but
// cannot because it is implemented in the base interfaces contract.
}
}
I get to here and i cannot figure out a nice clean way to add conditions to Initialise().
Edit2: If I had put a requires in this method i would of got an error like this
Warning 1 Contract class IEngine cannot define contract for method IInitialise.Initialise as its original definition is not in type IEngine . Define the contract on type IInitialise instead. IEngine .cs
Any ideas?
Any methods which are from an interface other than the one you're writing the contracts for should be marked abstract. The contracts for these methods will be inherited automatically, and you can't change them (or this would alter the meaning of the base interface, which doesn't make sense).
So you should have your base interface and its contracts:
[ContractClass(typeof(IInitialiseContract))]
public interface IInitialise
{
bool IsInitialised { get; }
void Initialise();
}
[ContractClassFor(typeof(IInitialise))]
public abstract class IInitialiseContract : IInitialise
{
public bool IsInitialised
{
get { return default(bool); }
}
public void Initialise()
{
Contract.Ensures(IsInitialised == true);
}
}
And your derived interface and its contracts (note abstract inherited ones):
[ContractClass(typeof(IEnginecontract))]
public interface IEngine : IInitialise
{
ICommandManager CommandManager { get; }
IDictionary<int, IEntity> World { get; }
}
[ContractClassFor(typeof(IEngine))]
public abstract class IEnginecontract : IEngine
{
public ICommandManager CommandManager
{
get
{
Contract.Ensures(Contract.Result<ICommandManager>() != null);
return default(ICommandManager);
}
}
public IDictionary<int, IEntity> World
{
get
{
Contract.Ensures(Contract.Result<IDictionary<int, IEntity>>() != null);
return default(IDictionary<int, IEntity>);
}
}
public abstract bool IsInitialised {get;}
public abstract void Initialise();
}
I don't think it's possible. I use code contracts extensively and as far as I can tell -- I remember having tried something like this myself -- your derived interface's code contract must include all conditions again, it cannot inherit them.
I have a helper class that does a simple but repetitive process on a List of entities. For simplicity, it's like this...
public static List<MyType> DoSomethingSimple(List<MyType> myTypes) {
return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}
I now need to add support for another type, but everything is identical... how do I avoid an increasing list of overloaded methods like this:
public static List<MyType> DoSomethingSimple(List<MyType> myTypes) {
return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}
public static List<MyOtherType> DoSomethingSimple(List<MyOtherType> myOtherTypes) {
return myOtherTypes.Where(myOtherType => myOtherType.SomeProperty.Equals(2)).ToList();
}
... and so on.
Here's two ways:
Use generics, and a common base class
Use interfaces
Method 1:
public class BaseClass
{
public int SomeProperty { get; set; }
}
public class MyType : BaseClass { }
public class MyOtherType : BaseClass { }
public class ClassWithMethod
{
public static List<T> DoSomethingSimple<T>(List<T> myTypes)
where T : BaseClass
{
return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}
}
Method 2:
public interface ICommon
{
int SomeProperty { get; set; }
}
public class MyType : ICommon
{
public int SomeProperty { get; set; }
}
public class MyOtherType : ICommon
{
public int SomeProperty { get; set; }
}
public class ClassWithMethod
{
public static List<T> DoSomethingSimple<T>(List<T> myTypes)
where T : ICommon
{
return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}
}
Now, if you try to make the method use the interface directly, like this:
public class ClassWithMethod
{
public static List<ICommon> DoSomethingSimple(List<ICommon> myTypes)
{
return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}
}
Then that would work if you have a List<ICommon> when you call it, but won't work if you have a List<MyType>. In C# 4.0 this can be done if we change the method slightly:
public class ClassWithMethod
{
public static List<ICommon> DoSomethingSimple(IEnumerable<ICommon> myTypes)
{
return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}
}
Note that I changed to using an IEnumerable<ICommon> instead. The concept here is called Co- and contra-variance, and beyond that I'm not going to say much about it. Search Stack Overflow for more information on the subject.
Tip: I would change the input parameter to be IEnumerable<T> regardless, since this would make your method usable in more instances, you could have different types of collections, arrays, etc. and as long as they contain the right type, they can be passed to the method. By limiting yourself to List<T> you force the user of your code to convert to a list in some cases. My guidelines are to be as unspecific as possible in input parameters, and as specific as possible in output parameters.
Assuming the property has the same name and type for each list type, you could add an interface containing the property and implement it for each type you want to call this method on:
public interface ISomeProperty
{
object SomeProperty { get; }
}
DoSomethingSimple could then be:
public static List<T> DoSomethingSimple<T>(IEnumerable<T> list) where T : ISomeProperty
{
return list.Where(i => i.SomeProperty.Equals(2)).ToList();
}