Use common extension methods
Free / chain methods work best as general extension methods. The general extension method knows the type of the instance variable and can return it as the same type that was passed.
class Animal
{
public string CommonProperty { get; set; }
}
class Dog : Animal
{
public string DogOnlyProperty { get; set; }
}
static class ExtensionMethods
{
static public T AnimalMethod<T>(this T o) where T : Animal
{
o.CommonProperty = "foo";
return o;
}
static public T DogMethod<T>(this T o) where T : Dog
{
o.DogOnlyProperty = "bar";
return o;
}
}
class Example
{
static public void Test()
{
var dog = new Dog();
dog.DogMethod().AnimalMethod();
dog.AnimalMethod().DogMethod();
Console.WriteLine("CommonProperty = {0}", dog.CommonProperty);
Console.WriteLine("DogOnlyProperty = {0}", dog.DogOnlyProperty);
var animal = new Animal();
animal.AnimalMethod();
}
}
Conclusion:
CommonProperty = foo
DogOnlyProperty = bar
Workaround if you need private / secure access
, . , . (, , LINQ, ). , , .
"chaining" - ( ) , . , .
interface IPrivateAnimal
{
Animal AnimalMethod();
}
interface IPrivateDog
{
Dog DogMethod();
}
class Animal : IPrivateAnimal
{
protected virtual string CommonProperty { get; set; }
Animal IPrivateAnimal.AnimalMethod()
{
this.CommonProperty = "plugh";
return this;
}
}
class Dog : Animal, IPrivateDog
{
private string DogOnlyProperty { get; set; }
Dog IPrivateDog.DogMethod()
{
this.DogOnlyProperty = "xyzzy";
return this;
}
}
static class ExtensionMethods
{
static public T AnimalMethod<T>(this T o) where T : class, IPrivateAnimal
{
return o.AnimalMethod() as T;
}
static public T DogMethod<T>(this T o) where T : class, IPrivateDog
{
return o.DogMethod() as T;
}
}
class Example
{
static public void Test()
{
var dog = new Dog();
dog.DogMethod().AnimalMethod();
dog.AnimalMethod().DogMethod();
Console.WriteLine("CommonProperty = {0}", typeof(Dog).GetProperty("CommonProperty", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(dog));
Console.WriteLine("DogOnlyProperty = {0}", typeof(Dog).GetProperty("DogOnlyProperty", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(dog));
}
}
:
CommonProperty = plugh
DogOnlyProperty = xyzzy