Can PropertyGrid be used without an object? - c#

I have an application in which I need to edit some data, and PropertyGrid structure is visually the best candidate for my needs. However, PropertyGrid takes the public properties of an object and displays them in the grid. (additional options with attributes). However, I don't have such an object, because the list of key-value pairs I need to edit is dynamic.
The ideal solution would be something like this:
public class GridParam
{
// ... several constructors here, one for each type
// ... or a single one but with generic class, does not matter
public String Name { get; set; }
public Object Value { get; set; }
public Type ItemType { get; set; }
}
GridParam stringParam = new GridParam("Address", "2534 Barkeley Av.");
GridParam numberParam = new GridParam("Year", 2012);
NewKindOfPropertyGrid grid = new NewKindOfPropertyGrid();
grid.AddParam(stringParam);
grid.AddParam(numberParam);
The above code would generate a property grid that looks like this:
Is something like this possible with PropertyGrid or any other existing control (which at least looks similar to PG)? The syntax does not have to be similar to what I've written, but it would need to be able to accept a collection of such properties that can be dynamic, without having to define a class...

You have two options here.
The first (and simpler, IMO) is to implement the ICustomTypeDescriptor interface on a class that takes an IEnumerable<T> of your GridParam instances.
The PropertyGrid class doesn't actually use reflection directly; instead, it uses a TypeDescriptor class to get metadata about an instance of an object, which by default uses reflection.
However, if you implement ICustomTypeDescriptor, then the PropertyGrid will get all the information it would get from a TypeDescriptor from your implementation. You just have to feed it what you want it to show.
So in this case, you'd have the GetProperties implementation return a PropertyDescriptorCollection populated with a PropertyDescriptor for each of your GridParam instances.
The other, much more difficult (possibly) option is to dynamically create the type, and have it bind to that (since PropertyGrid takes an object to bind to). Of course, you're really replicating on some level most of what an implementation of ICustomTypeDescriptor would do, so it's probably better to go with the former.

Related

IEnumerable versus List in a concrete class implementation

I am writing a class library for financial modeling.
I want to define the models using interfaces to create abstraction for testing, and the possible later addition of new concrete classes.
I am struggling on how to define lists of things, so I can later add to those lists in the concrete class.
For example, if I define an interface as having a list of expenses in my Model called
IEnumerable Expenses {get; set;}
and later want to create a concrete class called ABCModel with a list of concrete XYZExpense in it, what would be the best way to implement the lists so I can easily add more items to the list?
I cannot cast the List as a IEnumerable.
So for example:
public interface IFinancialModel
{
IEnumerable<IExpense> Expenses { get; }
IEnumerable<IRevenue> Revenue { get; }
IEnumerable<IAsset> Assets { get; }
IEnumerable<ILiability> Liabilities { get; }
}
I need a concrete class called public class FinancialModel : IFinancialModel
and be able to add concrete items.
Should I create 'Add' methods of my own? Ideally I would like to leverage built in List functionality and not reinvent the wheel.
It depends on what you actually want to do. Having List or IList properties is not recommended, because you can do everything with it (like Clear, Add and so on) without the owning class know about it. This is not good for encapsulation. You wouldn't be able to do something on change (like setting a dirty flag, fire changed events or do validation).
IEnumerable is a good choice.
You may add setters, but you shouldn't take the value that is set to the property by reference. It could be anything, like a Linq query or even a database query, which you don't want to reference to. You only want the items. (Also consider that the reference to the collection which comes from the outside can be assigned to other instances, which results in very bad side effects when it is changed there but shouldn't be changed here.)
// example implementation with a setter
private List<IExpense> expenses
public IEnumerable<IExpense> Expenses
{
get { return expenses; }
set { expenses = value.ToList(); }
}
Alternatively you may implement your own Add, AddRange, Remove or Clear etc. methods. However, if the main use case is to set all items in one go, you can only have a SetExpenses method, which is the same as the setter on the property I showed before. You may consider to keep it as an array internally.
What you are looking for is IList<T>. This is an interface that allows you to expose the lists while hiding the actual list implementation. For ex:
interface IFinancialModel {
IList<IExpense> Expenses { get; }
}
Then implement with a list that satisfies your needs. For example:
class FinancialModel : IFinancialModel {
private IList<IExpense> _expenses = new List<IExpense>();
IList<IExpense> Expenses { get { return _expenses; } }
}
I agree with #Stefan though, exposing a list breaks encapsulation and should generally be avoided.

Using list of objects to pass between layers of the project (C#)

In a C# (visual Studio 2010) project, I have a class with large number of properties, and I populate objects of this class with data and add to list object to pass it to display list of items (Something like results of a search).
My problem is there I don't need all the properties of the class to display the above list, so do I have to create another class only with required field to display the (results) list? Is it correct according to the OOP concepts?
Your properties object can implement multiple interfaces, as requested by different parts of your program.
If you define these interfaces:
public interface IBasicInfo
{
string Name { get; }
string Id { get; }
}
internal interface IFullInfo : IBasicInfo
{
string Address { get; }
}
internal interface IInternalStuff
{
Stuff Data { get; }
}
And your properties class implements them like this:
internal class Properties : IFullInfo, IInternalStuff
{
// some basic implementation
}
Then you can pass this class to a different part of your app which has a method like this:
public void Display(IBasicInfo info)
{
...
}
And the calling code will only see properties which belong to IBasicInfo. Note that only IBasicInfo needs to be public, and even the Properties class is internal to ensure that no calling code can cast back to the actual implementation and mess with it.
Alternatively, if your calling code contains completely different interfaces, then it is perfectly reasonable to convert them into Data Transfer Objects, and even modify their contents to match caller's expectations (adapter pattern). There are tools which automate this task (Automapper, for example).
I think yes, it is called Data transfer object
You might consider using a solution like automapper to map from a class that has N number of properties to another that has M number of properties. It relies on some conventional information (same/similar name) but can be tweaked too.
This is a pretty standard way of taking model data pulled from a DB and converting it into something that can be displayed on a view in webpage. I build a "viewmodel" that just has the stuff I want to display, which is typically a subset of the fields, and then map between them. Something like automapper makes it pretty easy to do so.
Since you have a reference type (a class), it shouldn't be costly to pass the original object rather than a new object containing a subset of the data.
If you want to protect the object from being manipulated by the recipient of the list, then you could define a read-only interface for the class, and pass it as that.

Setting Values on a derived class from the base class constructor using Reflection

I have two classes like this:
public abstract class MyBase
{
protected MyBase(){
Initialize();
}
protected IDictionary<string,string> _data;
private void Initialize() {
// Use Reflection to get all properties
// of the derived class (e.g., call new MyDerived() then
// I want to know the names "Hello" and "ID" here
var data = GetDataFromBackend(propertyNamesFromDerived);
_data = data;
}
}
public class MyConcrete : MyBase
{
public MyConcrete(){
// Possibly use Reflection here
Hello = _data["Hello"];
ID = new Guid(data["ID"]);
}
public string Hello {get;set;}
public Guid ID {get; set;}
}
As you see, I want the constructor of my base class to know about the properties of the derived class I'm instantiating.
Now, this seems like a huge and big code smell, so let me give some more background about my intentions, maybe there is a better way.
I have a backend system that stores Key/Value Pairs, essentially a Dictionary<string,string>. I want to abstract away working with this backend system in a way where people can create classes whose properties are Keys into the backend system. When they construct this object, it will automatically load the data from that system and initialize all the variables to it.
In other words, I've just reinvented serialization, except that I don't control the backend system and just rather make working with it really painless. I don't want callers to have to call Initialize() after constructing the object, because in 100% of the cases you have to initalize it after constructing.
I don't want to move the initialize code into the Derived Classes, except for string-to-business-object conversion.
Would I have to use a Factory? Or is it considered safe to look at the property names of a derived class in a base constructor? (Don't care about their values and that they aren't initialized, just need the names).
Or is there a better way altogether to provide a facade between a Dictionary of strings and a concrete business object?
Edit: This is .net 3.5, so no System.Dynamic which would make this trivial :(
Edit 2: After looking at the Answers and thinking through this some more, I guess my question really boils down to this now: Is calling GetType().GetProperties() from a base constructor in order to get the Names of Properties and if they are decorated with a certain Attribute safe?
Wait, let's stop here for a second and do this properly. It shouldn't be MyBase's responsibility to do this.
So you write a class that manages getting stuff out of the backend for you, and you write a method on that class that is something like
T Get<T>() where T : new()
and you make Get responsible for reading the dictionary out of the backend and using reflection to populate an instance of T. Thus, you say
var concrete = foo.Get<MyConcrete>();
This isn't hard, and it's the right way to do it.
Incidentally, the code for Get is going to look something like
T t = new T();
var properties = typeof(T).GetProperties();
foreach(var property in properties) {
property.SetValue(t, dictionary[property.Name], null);
}
return t;
where dictionary is your loaded up key/value pairs. It turns out there are more optimal ways to do this, but unless it's a bottleneck I wouldn't worry about it.
The better way to do this would be to make the classes use the dictionary directly:
public string Hello {
get { return (string)base.data["Hello"]; }
set { base.data["Hello"] = value; }
}
You may want to call TryGetValue in the getter so that you can return a default value if the key isn't there. (You should probably do that in a separate method in the base class)
You can make a code snippet to make the properties easier to create.
If you don't want to do it this way, you can call GetType().GetProperties() to get PropertyInfo objects for the properties in your class, then call SetValue(this, value).
This will be slow; there are various tricks you can use to speed it up using expression trees, CreateDelegate, or IL generation.
Maybe try the Template method pattern
Have you considered using an ExpandoObject? With it you can dynamically add properties and inspect them (when serializing for example).
I'm not sure if it's what you really should do, but here's what you asked for (put this in Initialize, and you'll get a list of the derived property names):
var derivedProps = this.GetType().GetProperties();
var propNames = new List<string>(derivedProps.Select(x => x.Name));
From there, using the PropertyInfos in derivedProps, you can set the properties.
You can't really safely do anything to those properties in the base-class constructor anyway as some derived constructor may reset them anyway. You're much better off doing a two-phased load (e.g. call Initialize explicitly)

How to create an IList of anonymous classes using AutoFixture

I previously posted a question on this link:
Class with a nested collection - how do I populate the nested class?
I need to be able to do the same but with nested classes:
like so:
public class ParentClass
{
public int Value;
public IList<ChildClass> Children;
}
public class ChildClass
{
etc...
}
I tried this:
Fixture.Register(()=>Fixture.CreateMany<ChildClass>();
But this isn't working, any ideas?
I'm using AutoFixture 2.0.
The AutoProperties features of AutoFixture only assigns values to writable properties. The reason why ParentClass.Children isn't being populated is because it's a read-only property - AutoFixture doesn't attempt to assign a value because it knows that this is impossible.
However, assuming that you already have an instance of ParentClass, you can ask AutoFixture to fill the collection for you:
fixture.AddManyto(parentClass.Children);
This can be encapsulated into a customization like this:
fixture.Customize<ParentClass>(c => c.Do(pc => fixture.AddManyTo(pc.Children)));
Since Children is an IList<ChildClass> you'll also need to provide a mapping for that unless you use the MultipleCustomization:
fixture.Register<IList<ChildClass>>(() => fixture.CreateMany<ChildClass>().ToList());
This is definitely a behavior that we considered adding to the MultipleCustomization, but decided to postpone until after release 2.1 because it turns out to be not entirely easy to implement.

Make properties available for data binding through some kind of interface in .NET?

I have a class that implements properties in a specific way, to handle some custom requirements for our business logic system.
This "specific way" makes the properties non-operational in the context of data binding. Basically, if I drop an object of our class onto a form, data binding finds nothing on the object, and the property inspector for that object, though it lists the properties, doesn't allow me to edit them.
What I'm wondering is if there's an interface or similar that I can implement in my class that will report to the form designer what properties could be bound to, and that implements the custom code necessary to talk to the data binding system on behalf of my properties.
Note that I do not need to be able to edit the property values for my object in the property inspector, that was just an example of how non-functional the properties are. I just need the data binding support.
Is there such an interface, and if so, what is it?
Let's give a simple example.
Let's assume I have this class:
public class CustomDataBinding : Component
{
private Dictionary<String, Object> _Properties = new Dictionary<String, Object>();
public CustomDataBinding()
{
_Properties["Property1"] = 10;
_Properties["Property2"] = "Test";
}
}
Is there anything I could do to my object, short of actually making the properties, that would add data binding support for those two "properties"?
Note that for my real class, I know the type of every property, so if it makes it easier, change the above code to just use string values:
public class CustomDataBinding : Component
{
private Dictionary<String, String> _Properties = new Dictionary<String, String>();
public CustomDataBinding()
{
_Properties["Property1"] = "Property1";
_Properties["Property2"] = "Property2";
}
}
I will also need validation support, as our class can report validation status for every property as well, but I have already implemented IDataErrorInfo and IDataValidationInfo which I think will give me that. I have also implemented INotifyPropertyChanged, so I got the change mechanism in place I think, but I need to discover and talk to the properties. Beyond those interfaces, anything else I should look into would be welcome information.
It sounds like you are describing a property-bag; this is indeed supported for data-binding, but you need to implement ICustomTypeDescriptor or TypeDescriptionProvider. The available properties are then defined via TypeDescriptor.GetProperties(obj) or TypeDescriptor.GetProperties(type) - or in the case of lists, via ITypedList. ICustomTypeDescriptor is suitable if the properties change per-instance; TypeDescriptionProvider can do per-type customisation, and works with things like BindingList<T> without any extra work.
The tricky thing is that you need to define the type of each property - not simple if you've just got object. Here is a very simplified example, that treats all properties as strings. In this example, because we are binding a list, it uses ITypedList but doesn't implement ICustomTypeDescriptor.
Note that for PropertyGrid, a simpler shortcut is to use a TypeConverter - this allows you to tweak the properties without having to use ICustomTypeDescriptor or TypeDescriptionProvider - see example.
You could always expose the Dictionary as a property and access elements of it directly (though it'd need to be by index and implement IListSource or IEnumerable.
-- Edit
I must say, though, you're effectively making your own untyped language. Interested in the reason for this, perhaps there is a better way ...
Since you can't publish new properties, how about publishing your Dictionary as an ObservableDictionary<string, object>. See this DrWPF article.
You could then bind to the dictionary using the key to get the named property you're after.

Categories

Resources