by Moridin8
7. March 2007 19:55
For a few of the '##csharp' guys:
See the code for comments and implementation...
namespace ExplicitInterfacesForVersioning
{
using System;
public interface ISomeClass_Version2
{
string DoSomethingElse();
}
public interface ISomeClass_Version3
{
string Something { get; }
string DoSomethingElse();
string DoSomethingElseAgain();
}
public class SomeClass : ISomeClass_Version2,
ISomeClass_Version3
{
// 0=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=O Original O=~~~~~~~~~~~~~~~~~~~~~~~~~~~=O
// These various members represent an original implementation.
// *** these of course should never be altered unless it's a bug.
// *** If it is no longer valid, it should be marked with the
// *** ObsoleteAttribute, it's not until the ObsoleteAttribute is
// *** marked so that it disallows compile should the code within be
// *** COMMENTED OUT and replaced with a
// *** 'throw new NotSupportedException()'
// *** incase of casual late-binding or reflection access.
// *** The actual method stubs should not be removed!
public string Something
{
get { return "DoSomething - Version 1"; }
}
public void DoSomething()
{
Console.WriteLine(this.DoSomethingElse());
}
public string DoSomethingElse()
{
return this.Something;
}
// 0=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=O Version 2 O=~~~~~~~~~~~~~~~~~~~~~~~~~~=O
// This represents a subsequent version that requires a slightly different
// functionality requirement from a method. This method is only visible
// though the explicit interface definition used below. this also shows that
// the original implementation is of course still available.
//
// of course, after formal release, the same no-touch philosophy applies
// and any future work must be part of a version 3 interface.
string ISomeClass_Version2.DoSomethingElse()
{
return this.Something.Replace('1', '2');
}
// 0=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=O Version 3 O=~~~~~~~~~~~~~~~~~~~~~~~~~~=O
// This represents yet another subsequent version. This shows further
// requirement differences from the members within the class.
//
string ISomeClass_Version3.Something
{
get { return "DoSomething - Version 3"; }
}
string ISomeClass_Version3.DoSomethingElse()
{
// To access the newer version of the property, use this...
return ( this as ISomeClass_Version3 ).Something;
}
string ISomeClass_Version3.DoSomethingElseAgain()
{
// this demonstrates that it is still ok to reference to previous
// explicitly interfaced methods... again using the interface cast.
return ( this as ISomeClass_Version2 ).DoSomethingElse()
+ " Called from V3!";
}
}
internal class Program
{
private static void Main()
{
SomeClass original1 = new SomeClass();
Console.WriteLine(original1.Something);
original1.DoSomething();
Console.WriteLine(original1.DoSomethingElse());
ISomeClass_Version2 iV2A = original1;
Console.WriteLine(iV2A.DoSomethingElse());
ISomeClass_Version3 iV3A = original1;
Console.WriteLine(iV3A.DoSomethingElse());
Console.WriteLine(iV3A.DoSomethingElseAgain());
// above is same as below. It shows no difference
// even if individually instantiated...
SomeClass original2 = new SomeClass();
Console.WriteLine(original2.Something);
original2.DoSomething();
Console.WriteLine(original2.DoSomethingElse());
ISomeClass_Version2 iV2B = new SomeClass();
Console.WriteLine(iV2B.DoSomethingElse());
ISomeClass_Version3 iV3B = new SomeClass();
Console.WriteLine(iV3B.DoSomethingElse());
Console.WriteLine(iV3B.DoSomethingElseAgain());
Console.ReadLine();
}
}
}