Click here to Skip to main content
15,867,771 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am struggling with this concept and I know I should not be; but for some reason I'am just mentally blocked right now.

I have 3 classes, my POCO and two 3rd Party classes and I am trying to map the property value of a 3rd party class object to one of the elements in my POCO .(which I am using as an Intermediary to update a database, and a UI with via WCF) [Maybe I am using a bad approach but I am not sure on this]. See the code below along with the explanatory below it.

C#
public List<Machine> Machines;
public List<Item> MachineItems;

public class Machine : IMachine
{
 [DataMember]
 double SensorA {get; set;}

 [DataMember]
 double SensorB {get; set;}

 [DataMember]
 string Sytem1 {get; set;}
}
public class ItemValue : Item
{
 object value;
}
public class Item
{
 object clientID;
 System.Type sysType;
}
OnNewlyReadValues(ItemValue[] itemValues)
{
   // each itemValue in itemValues represents a property
   // in the POCO .
   // itemValues May contain one itemValue or all itemValue
   // that represent the values in the POCO.
   // Determine if itemValue is for which Machine.PropertyName
   // property SensorA  (or any of the properties)
   // Machine.Property = itemValue.Value;

}

I can only Modify Machine Class, the other two classes belong to a 3rd party library, which expects these two types to be passed in; [Maybe I do not know enough to know how to get around that].

I instantiate the Item as a new Item with parameters clientID etc. so I have the clientID and pass this Item object on to the 3rd party Library.

The OnNewlyReadValues is an event from the 3rd party library and has arguments of ItemValue[] - each itemValue object has a property named "Value" and represents a Property in my POCO. ItemValue also has my clientID from myItem that I passed to the 3rd party library.

I am trying to map this ItemValue.Value property to the POCO, in a very efficient manner the Items will not change often, but the Value property will.

What is the best way to do this , given the example above ? Any examples are appreciated,, ItemValue has the clientID as an Identifier which matches my Item.ClientID.
Posted
Updated 20-May-15 6:21am
v2
Comments
Tomas Takac 19-May-15 17:45pm    
I don't get it. How do you know which value is for which property? e.g. you create an Item with clientID=123 then you get back ItemValue with clientID=123, but how can you tell it's the value for SensorA or SensorB?
stixoffire 20-May-15 11:23am    
I create the Item and assign the clientID then add it to the 3rd party servers list of Items[],
1: I can at creation time create a separate dictionary , <clientid,propertyname>
2: I also thought about encapsulating Item and adding the string propertyName, object propertyValue (which I will need to box and unbox), Type dataType.

When any Item of Items[] changes with in the 3rd party server a callback event OnDataChanged is fired with the argument of ItemValues[] (and they are derived from my Items so the clientID property is in the ItemValue) - I can match that up to what I created.

Say for example my POCO represents ItemValues[0-10] (the index 0-10 is an example could be any non sequence as well). I could have 100 or 1000 ItemValues[].

So I need to iterate them correlate them to the POCO Properties and when done my POCO is ready.


In Method 1 I only have a propertyName - I cant say POCO.[Dictionary Key ClientID, Property] = ItemValue.Value (would be very nice though).

In Method 2 I could iterate ClientId and set my PropertyValue to the ItemValue, but then I still need to translate the PropertyValue into the Poco object

Of course maybe I should make a DataTable of the POCO which would leave the row for me to know what client IDs make up that row. [Perhaps dictionary<rowid ,clientid="">]
So I would have ROW[0].Column[dictionaryLookup<clientid, propertyname="">] = ItemValue.Value

Basically I have a collection of objects with a property value that represents the POCO , or should I build my collection of Item[] as if it was the POCO, using the setter to update the property - I am at a loss - because I want to store data in database and also to use WCF to automagically display the real time info in a datagrid on a winform.


I know I need to Iterate the collection ItemValues[], look up the clientID some how and map back to the POCO property. The more generic the better. The simpler the better .

I hope this makes it more clear.
Sascha Lefèvre 19-May-15 18:07pm    
It's not really clear to me... how are you/anybody supposed to know to which Machine-object you need to map and to which of its properties if all that an ItemValue-object holds is a "value"? Are you sure you did show here everything that is relevant?
stixoffire 20-May-15 11:25am    
I create the Item[] with the clientID, transfer that to the 3rd party server, it send back the ItemValue[] in a callback event - so I can match the two up . Now I need to be able to use this clientID to match it up to a property in my POCO.

1 solution

From your explanation I understand you are able to map a clientID to a property. It still feels like magic and it's possible that I'm missing something but let's assume you can do the translation.

Your idea about building a dictionary is correct. It should be a dictionary of setters:
C#
public Dictionary<object, Action<machine,object>> setters = new Dictionary<object, Action<machine,object>>
{
    {1, (m,v) => m.SensorA = (double)v},
    {2, (m,v) => m.SensorB = (double)v},
    {3, (m,v) => m.System1 = (string)v},
};

The key is the clientId. The value is a the setter - an action which takes the POCO and the item value and does the assignment.

This might seem as an overkill but will make things it a lot easier in the event handler:
C#
public void OnNewlyReadValues(ItemValue[] itemValues)
{
    var machine = new Machine();
    
    foreach(var itemValue in itemValues)
    {
        var setter = setters[itemValue.clientID];
        setter(machine, itemValue.value);
    }
    
    // your POCO is initialized
}

Based on the clientID you retrieve the setter and apply it on your POCO and item value.

Edit - multiple machines
If I understand you correctly then you want to use the same Machine instance trough the life of the client class.

Create a class that will encapsulate client ID. In your third party library the clientID is an object so you can put whatever you want there:
C#
public class ClientId
{
    public Machine Machine { get; set; }
    public int SetterKey { get; set; }
}

The SetterKey is the key in the dictionary. Actually you can change that into simple array and SetterKey will then become SetterIndex. You initialization will look something like this:
C#
Machines = new List<Machine>
{
    new Machine(),
    new Machine()
};

MachineItems = new List<Item>
{
    new Item { clientID = new ClientId { Machine = Machines[0], SetterKey = 1 }},
    new Item { clientID = new ClientId { Machine = Machines[0], SetterKey = 2 }},
    new Item { clientID = new ClientId { Machine = Machines[0], SetterKey = 3 }},
    new Item { clientID = new ClientId { Machine = Machines[1], SetterKey = 1 }},
    new Item { clientID = new ClientId { Machine = Machines[1], SetterKey = 2 }},
    new Item { clientID = new ClientId { Machine = Machines[1], SetterKey = 3 }},
};

Again all this is will make the code in the event handler much easier. You have the Machine instance embedded directly in the clientID.
C#
public void OnNewlyReadValues(ItemValue[] itemValues)
{
    foreach(var itemValue in itemValues)
    {
        var clientId = (ClientId) itemValue.clientID;	
        var setter = setters[clientId.SetterKey];
        setter(clientId.Machine, itemValue.value);
    }
}
 
Share this answer
 
v3
Comments
Sascha Lefèvre 20-May-15 20:23pm    
I also think this would be the solution. Will upvote if he accepts :)
(I added "object" to the Actions)
/Sascha
stixoffire 20-May-15 23:53pm    
I have never worked with Action keyword - so I am looking this up on MSDN and also CodeProject . I like this - it seems so straight forward , clean and simple.
stixoffire 21-May-15 1:15am    
Just a quick question now that I am reading more about this: I am building my Item[] in a list - which represents one machine, I will have several machines , Machine[] this will be in this client processing class as a property. Getting a quick resolve is obvious to keep track of all machines[] with their clientID[] (list of an array) the dictionary<object, Action<int,machine,object>> , I think I will need to modify with 3 parameters , the index of Machines[index] and modify my setters with the added parameter to get to the index of m[index].SensorA.
Is this the correct way to do it ?
I still can't get over how simple and clean this code is - I have been racking my brain and all my code looked like crud (pardon the pun.)
I can't wait to start coding tomorrow!
Tomas Takac 21-May-15 3:33am    
I updated the solution. Have a look if that would work for you.
stixoffire 21-May-15 9:58am    
As I am looking at this today after a little sleep; there seems to be a problem
My clientID is not representive of the POCO but is representative of a property in the POCO (SensorA).
Given this though you have a valid and important point clientID is an object and currently when I create it I give it a guid for uniqueness; because it must be unique according to the 3rd party library,typical examples use integers.
I could just name my clientID like this GUID.PropertyName
that way I could keep track of Machine[0]= GUID [POCO], its properties would be .Property,
[POCO.Property] and as your example is using a dictionary GUID as key represents machine (POCO), then Property is property of POCO.
I will need some time looking at what you provided this morning as well, I am very excited with what you provided - I never used action nor thought I could use dictionary that way! I think I am getting to where I need to be. Your help is GREATLY Appreciated!!!!! I wish I could give you 10 stars, because this is outstanding!!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900