public interface ITest {
void Somethink();
}
public class Test1 : ITest {
public void Somethink() { /* do stuff */ }
public int Test1Property { get; set; }
}
public class Test2 : ITest {
public void Somethink() { /* do stuff */ }
public float Test2Property { get; set; }
}
//Main class
public class MainClass
{
[TypeConverter(ExpandableObjectConverter)]
public ITest test { get; set; }
}
Ok, i have sth like this. Instance of MainClass is selected by PropertyGrid.
How to make a DropDownList of objects of classes which implement ITest (here Test1 and Test2)
That's not how it works. The test property getter will return an object of a concrete class that implements ITest. Whatever was assigned to it last, either null, an object of Test1 or an object of Test2. PropertyGrid uses Reflection to look at the object Type and its members. It will display either Test1Property or Test2Property. You cannot choose.
Not sure what you are trying to do, you probably want a UITypeEditor if you want to assign an object of a different type.
Ok, I used UITypeEditor (thx nobugz), and create combobox for possible values. The values i get from Type[] BehaviorManager.GetBehaviorsWhichImplement(Type type) - that return an array of types implementing given interface.
When user have select a new value, i get a new instance of selected Object BehaviorManager.GetBehavior(Type) which using a Activator.CreateInstance. And assign it to Property.
Of course, it isn't a dropdownlist, but it's pretty good too :-)
here is a article which i following - http://philwinkel.com/blog/?p=4
I know, my grammer is tragic, sorry, i'm still trying to do sth with this ;-)
Related
I've got some weird behaviour in Moq 4.2. When I make a mock of an abstract class which implements an interface which defines properties, I can access the properties just fine, as long as the instance is the original type. If I cast that instance to the underlying interface, the properties return default values.
See below for an example. Anyone have a solution to this?
In the example below, doing foo.As<IFoo>() does not help.
public interface IFoo { string Thingy { get; } }
public abstract class Foo : IFoo
{
public Foo() { Thingy = "Howdy"; }
public string Thingy { get; }
}
public class Test
{
public void DoIt()
{
var foo = new Mock<Foo>();
Console.WriteLine(foo.Object.Thingy); // prints "Howdy"
Console.WriteLine((foo.Object as IFoo).Thingy); // prints nothing
}
}
Mock - generates a proxy of some object with its own implementation.
proxyImpl1 : IFoo { string Thingy => default }
call Thingy return proxied property
proxyImpl : Foo {nothing, since the parent object does not contain virtual methods} call Thingy return parent non-overrided property.
POCO works the same way in EF
Im not sure if it is possible. I am running into a unique issue dealing with a clients api.
I am needing to extend a class and add a bool property that does not exist in the base class.
below is an example of what I am trying to accomplish.
public class baseClass
{
//.. No Editable Access
}
public class Extended
{
public bool flaggedAsDeleted(this baseClass bc)
{
//Idealy was looking for get; set; but I know that don't work
return true;// Need to know if possible to set property on baseClass or Alternative
}
public void flagAsDeleted(this baseClass bc)
{
flaggedAsDeleted = true;
}
}
public class program
{
public void doit()
{
baseClass bc = new baseClass();
bc.flagAsDeleted();
}
}
If you're trying to actually extend a class, you do it like this:
public class BaseClass
{
//.. No Editable Access
}
public class Extended : BaseClass
{
public bool FlaggedAsDeleted { get; set; }
}
If you're trying to add data to an existing class, you have two options:
Inheritance - as seen above.
Encapsulation - create a new object that holds an instance of the type you're adding to.
C# provides a feature called Extension Methods, which allows you to seemingly add methods to existing classes. However, these are really just syntactic sugar, as you're still constrained to the class's public API.
public class BaseClass
{
public int Value { get; set; }
}
public static class ExtensionMethods
{
public static void Increment(this BaseClass b)
{
b.Value += 1;
}
}
Extension methods do not allow you to add data to an existing class though.
This is not unique. This is a common problem solved using a Design Pattern called decorator.
Consider the following code:
public dynamic DataGrid { get; private set; }
public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class
{
return DataGrid = new DataGridForm<TData, TGrid>();
}
I'm trying to keep an instance of a generic class in a property for later usage, but as you know:
Properties, events, constructors etc can't be generic - only methods
and types can be generic. Most of the time that's not a problem, but I
agree that sometimes it's a pain (Jon Skeet)
I want to know is this a good way to round this situation?
As the answer in the comment indicated, you can do this with a base class or an interface:
class DataGridForm {}
class DataGridForm<TData, TGrid> : DataGridForm {}
class GridConfigurator
{
public DataGridForm DataGrid { get; private set; }
public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class
{
return DataGrid = new DataGridForm<TData, TGrid>();
}
}
A ton of types and interfaces in C# were expanded this way when generics were added. However, I would probably re-evaluate your design so that perhaps whatever called GridConfig() was caching the DataGridForm since it knows the types. As an example, I do a very similar thing in my code:
class Vector<T> { ... }
static class Vector
{
public static Vector<T> Create<T>(T value)
{
return new Vector<T>(value);
}
}
class OtherClass
{
public static Vector<int> MyVector = Vector.Create(1);
}
Your specific use case may not support this style though.
In this case your type itself has to be generic.
class GridConfigurator<TData, TGrid>
where TData : class
{
public DataGridForm<TData, TGrid> DataGrid { get; private set; }
public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>()
{
return DataGrid = new DataGridForm<TData, TGrid>();
}
}
But I don't understand the purpose of this class. The GridConfig method has a non-obvious side effect of setting the DataGrid property (which has a private setter). If I were using this class, I would never guess that the value that GridConfig() returns to me is also set as the DataGrid property. In other words:
var configurator = new GridConfigurator();
var firstGrid = configurator.GridConfig();
var firstReference = configurator.DataGrid;
var secondGrid = configurator.GridConfig();
var secondReference = configurator.DataGrid;
I would assume the following would return false:
object.ReferenceEquals(firstGrid, secondGrid);
But I would assume this would return true:
object.ReferenceEquals(firstReference, secondReference);
Because at no point in the above code do I ever assign the DataGrid property. It is not clear that a method called GridConfig() would have that effect.
Making the enclosing type (GridConfigurator) also generic seems to defeat the purpose of what you're trying. Why would anyone use this type when they could just use a direct reference to DataGridForm instead?
If the GridConfig method is supposed to do something more than just assign a new default instance of DataGridForm, then make it a static factory class like this:
static class GridConfigurator
{
public static DataGridForm<TData,TGrid> GridConfig<TData, TGrid>(...) where TData: class
{
var grid = new DataGridForm<TData,TGrid>();
// do something with the parameters to this method to initialize the instance.
return grid;
}
}
I would also name the method something other than GridConfig. Like Configure() or Create().
I have the following abstract class:
public abstract class BaseClass{
public object contents { get; set; }
public Action<BaseClass> mutator;
public abstract void Initialise();
}
This will be used by several classes, which will override the Initialize method to assign a value to contents, which will in turn be mutated using the mutator delegate at specific points in time.
I have the following static class, with each method intended to be used as a mutator:
public static class Mutators{
public static void VariantA(A inputObj){
// inputObj.contents = something else
}
public static void VariantB(A inputObj) { } // etc. etc.
}
I then have class A, which implements BaseClass. I am trying to assign Mutators.VariantA to the mutator delegate, but i'm not able to.
public class A : BaseClass{
public A(){
mutator = Mutators.VariantA;
}
public override void Initialise(){
/* set the value of contents property here */
}
}
Specifically I get the following error: A method or delegateMutators.VariantA(A)' parameters do not match delegate System.Action<BaseClass>(BaseClass)' parameters (CS0123)
I understand that Mutators.VariantA(A) requires an object of type A, and the Action was declared to accept an input of type BaseClass, however as class A implements BaseClass I thought I would have been able to do this ?
Coming from dynamically typed languages i'm having a tough time getting to grips with working with types in this way :(
Is there any way I can point to a function with an input of the abstract type in this way ? Do I need to look at some other design pattern ?
Thanks
I understand that Mutators.VariantA(A) requires an object of type A, and the Action was declared to accept an input of type BaseClass, however as class A implements BaseClass I thought I would have been able to do this ?
Absolutely not.
An Action<BaseClass> has to be able to accept any BaseClass object. So for example, if your code were valid, I would be able to write:
Action<BaseClass> mutator = Mutators.VariantA;
mutator.Invoke(new B());
(Where B is another class derived from BaseClass.)
The fact that B derives from BaseClass makes it valid for the invocation - but it's not going to help your VariantA method work nicely.
It's not really clear why you have a mutator here - I strongly suspect you should abstract BaseClass from its mutations. I still don't follow what you're trying to achieve, but this design pattern isn't going to help you get there in a type-safe way.
You could write:
public abstract class BaseClass<T> where T : BaseClass<T> {
public object Contents { get; set; }
public Action<T> Mutator { get; set; }
public abstract void Initialise();
}
... then:
public class A : BaseClass<A> {
public A() {
Mutator = Mutators.VariantA;
}
}
... as then you'd be writing something which can mutate "A" values. But in my experience this sort of generic nesting gets really messy, really quickly.
I've used your current example and changed the Method Signature of one of the classes to the following and it works
public abstract class BaseClass
{
public object contents { get; set; }
public Action<BaseClass> mutator;
public abstract void Initialise();
}
public static class Mutators
{
public static void VariantA(BaseClass baseClass)
{
// inputObj.contents = something else
}
public static void VariantB(A inputObj) { } // etc. etc.
}
public class A : BaseClass
{
public A()
{
mutator = Mutators.VariantA;
}
public override void Initialise()
{
/* set the value of contents property here */
}
}
I have the following class hierarchy:
public abstract class BaseClass : IBaseInterface
{
public int PropertyA{
get
{
return this.propertyA;
}
set
{
this.propertyA = value;
// ... some additional processing ...
}
}
}
DerivedClassB : BaseClass
{
// some other fields
}
public class ContainingClassC
{
public IBaseInterface BaseInterfaceObjectD
{
get;
set;
}
}
Now, in order to access PropertyA of a DerivedClassB-Object (inherited from BaseClass), I have to cast the object to BaseClassA's ancestor, like so:
// This ContainingClassC is returned from a static, enum-like class:
// containingObject.PropertyA is DerivedClassB by default.
ContainingClassC containingObject = new ContainingClassC();
((IBaseInterface)containingObject.BaseInterfaceObjectD).PropertyA = 42;
Is there a way I can restructure these classes to do away with the cast? This code is part of a library, and my colleague wants me to get rid of the cast.
The goal is to simply write containingObject.BaseInterfaceObjectD.PropertyA = 42.
First of all in the line ((IBaseInterface)containingObject.BaseInterfaceObjectD).PropertyA = 42; you are casting the member to the same type that it is declared in, so the casting doesn't actually do anything.
To be able to access the PropertyA in the derived class - since you are casting it to an interface - the property must be declared in the interface and then implemented in the BaseClass.
public interface IBaseInterface{
int PropertyA{get;set;}
}
public abstract class BaseClass : IBaseInterface{
public int PropertyA{
get{ return this.propertyA;}
set {this.propertyA = value;}
}
}
As long as the interface is implemented properly, ProprtyA should be available in the base class, the derived class or with either of them cast'ed to the interface type.
If it's just a problem of the property not showing up in IntelliSense, then it might be a problem with your settings. Check out Options->Text Editor->C# and make sure you have IntelliSense turned on and not set to hiding anythig.