5

I'm developing a Desktop Applicaiton which is akin to a plugin based system. I have a client module, that will load a DLL containing a 'Machine' object. Thereafter the 'Machine' object is manipulated and used as per well defined interfaces.

The tricky part is that the DLL containing the 'Machine' object is generated on the fly by using another program. At it's core, the DLL generating application accepts user input, generates classes, in c# code files (which contain fields specified by the user, of which I don't have any prior knowledge of) and compiles those classes to a DLL (machine.dll file).

The client program picks up this dll, dynamically loads it and then operates on this machine bject.

I am facing a lot of trouble modeling a solution to address the problem of passing data between the Machine object and the Client program, essentially because I dont know what data is contained in the machine object.

The client program is to do the following things.

-- Load the dll and instantiate the 'machine' object. -- Call a series of functions in the 'machine' object, that are known to the client via an interface. -- Extract various variables from the 'machine' object and display it to the user.

I am not able to perform the last step.

Note: I have programmed a trivial solution where the meta-data about the fields is generated by the dll generating program and stored in xml files. The client program uses these xml files to get information about the fields stored in the machine object. It then uses reflection on the machine object to access the fields of the object.

I feel this is cumbersome and slow. Are there any patterns or methods to this kind of stuff??

  • Did you look at the Managed Extensibility Framework(MEF)? http://mef.codeplex.com/ http://msdn.microsoft.com/en-us/library/dd460648.aspx – spender Dec 14 '12 at 04:29
  • I have heard of it and I have a brief idea of it's usage. The thing is that I am new to programming and I want to implement a solution that is readily portable to other languages and systems. Also, I want to really learn to implement these complex systems. – Raghavendra Kumar Dec 14 '12 at 04:32
  • Implementing it in C# makes it portable to other systems as there is Mono, which is a port of the .Net framework that runs on Linux and other platforms. I wouldn't necessarily worry about making it so generic though that it would port to other languages quickly. Each language and platform has its own set of idioms and best practices, and something that works well in one may not work well in another. – Maurice Reeves Dec 14 '12 at 04:43
  • @MauriceReeves You are right ! But what I meant to say was that I want to learn the underlying principles. Say I want to do the same thing in C++, I must have a solid understanding of the concepts and various practices to do this sort of thing. – Raghavendra Kumar Dec 14 '12 at 04:45
  • Fair enough. Below I've given you one possible way in .Net to accomplish it. If you want to rewrite in C++, you're on your own. :-D – Maurice Reeves Dec 14 '12 at 05:13

2 Answers2

3

A solution that came to mind when I read this was to make use of the built-in support for Attributes in C#. An attribute is a way of tagging a property, field, method, class, etc with some additional meta-data that is then used by some other class, for example during Serialization. You will see it there most often.

I had an application that I was building that needed to be able to take an IEnumerable collection of objects and output some data to a file based on user selected choices. I created an attribute class that gave me the ability to read the choices via reflection, and act as directed. Let me show you the example:

First the attribute class:

[System.AttributeUsage(AttributeTargets.Property)]
class ExportOptionsAttribute : System.Attribute
{
    public string Header { get; set; }
    public string FormatString { get; set; }
    public bool Export { get; set; }
    public int Order { get; set; }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="header"></param>
    public ExportOptionsAttribute(string header) : this (header, null, true)
    {

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="header"></param>
    /// <param name="formatString"></param>
    /// <param name="export"></param>
    public ExportOptionsAttribute(string header, string formatString, bool export)
    {
        this.Header = header;
        this.FormatString = formatString;
        this.Export = export;
        this.Order = 0;
    }
}

With this class defined like so, I could decorate my data class properties like this (actual properties changed so as to not get lost on the business jargon):

public sealed class PartsOrder
{
    /// <summary>
    /// 
    /// </summary>  
    [ExportOptions("Customer Name", Order=0)]
    public string CustomerName { get; set; }

    /// <summary>
    /// 
    /// </summary>
    [ExportOptions("Catalog Name", Order = 1)]
    public string Catalog Name { get; set; }

    /// <summary>
    /// 
    /// </summary>
    [ExportOptions("Unit", Order = 2)]
    public string Unit { get; set; }

    /// <summary>
    /// 
    /// </summary>
    [ExportOptions("Component", Order = 3)]
    public string Component { get; set; }

    /// <summary>
    /// 
    /// </summary>
    [ExportOptions("Delivery Point", Order = 4)]
    public string DeliveryPoint { get; set; }

    /// <summary>
    /// 
    /// </summary>  
    [ExportOptions("Order Date", Order = 5)]
    public string OrderDate { get; set; }
}

So then in my export routine, instead of hard-coding the property names, which are variable, or passing a complex data structure around which contained the information on which fields to show or hide and what the ordering was, I just ran the following code, using reflection, to loop the properties and output their values, to a CSV file in this case.

StringBuilder outputDoc = new StringBuilder();

// loop through the headers in the attributes
// a struct which decomposes the information gleaned from the attributes
List<OrderedProperties> orderedProperties = new List<OrderedProperties>();

// get the properties for my object
PropertyInfo[] props =
    (typeof(PartsOrder)).GetProperties();

// loop the properties
foreach (PropertyInfo prop in props)
{
    // check for a custom attribute
    if (prop.GetCustomAttributesData().Count() > 0)
    {
        foreach (object o in prop.GetCustomAttributes(false))
        {
            ExportOptionsAttribute exoa = o as ExportOptionsAttribute;

            if (exoa != null)
            {
                orderedProperties.Add(new OrderedProperties() { OrderByValue = exoa.Order, PropertyName = prop.Name, Header = exoa.Header, Export = exoa.Export });
            }
        }
    }
}

orderedProperties = orderedProperties.Where(op => op.Export == true).OrderBy(op => op.OrderByValue).ThenBy(op => op.PropertyName).ToList();

foreach (var a in orderedProperties)
{
    outputDoc.AppendFormat("{0},", a.Header);
}

// remove the trailing commma and append a new line
outputDoc.Remove(outputDoc.Length - 1, 1);
outputDoc.AppendFormat("\n");


var PartsOrderType = typeof(PartsOrder);

//TODO: loop rows
foreach (PartsOrder price in this.Orders)
{
    foreach (OrderedProperties op in orderedProperties)
    {
        // invokes the property on the object without knowing the name of the property
        outputDoc.AppendFormat("{0},", PartsOrderType.InvokeMember(op.PropertyName, BindingFlags.GetProperty, null, price, null));
    }

    // remove the trailing comma and append a new line
    outputDoc.Remove(outputDoc.Length - 1, 1);
    outputDoc.AppendFormat("\n");
}

The code for the OrderedProperties struct is here:

struct OrderedProperties
{
    /// <summary>
    /// 
    /// </summary>
    public int OrderByValue;
    /// <summary>
    /// 
    /// </summary>
    public string PropertyName;
    /// <summary>
    /// 
    /// </summary>
    public string Header;
    /// <summary>
    /// 
    /// </summary>
    public bool Export;
}

As you can see, the logic to extract the property values is completely ignorant of the structure of the class. All it does is find the properties that are decorated with the attribute I created, and use that to drive the processing.

I hope this all makes sense, and if you need more help or clarification, please feel free to ask.

Maurice Reeves
  • 1,572
  • 13
  • 19
  • You are generating the code without knowing what are the properties in the object that is sent to you. So to use your solution in my program, I have to change my code-generating module to include these attributes in the .cs files that I am generating on the fly. I will implement this for now. Thanks. However, do you know any other methods to do the same thing in a much more low-level fashion. Isn't the compiler doing what I am doing, but a bit more intrinsically? I doubt it is using reflection too. Am I right?? – Raghavendra Kumar Dec 14 '12 at 05:27
  • 1
    Yes, that would be correct. But the tradeoff is a much simpler set of processing at your end. Think of attributes as stackable metadata for your fields and methods. As long as you know what attributes to expect, you can do your munging of data, and displaying while knowing very little about the actual objects returned to you. [Also, the values of the attributes can be set at runtime if you need.](http://stackoverflow.com/questions/51269/change-attributes-parameter-at-runtime) – Maurice Reeves Dec 14 '12 at 05:33
  • Do you know how to implement the above solution in c/c++?? Or maybe documentation that is relevant to what you have done? I'm so insisting on c/c++ because coding in those languages makes it really easy to understand the working of the solution at a more bare-bones level. – Raghavendra Kumar Dec 14 '12 at 05:35
  • 1
    There's a bit more going on in a compiler. The set of steps a compiler can go through include lexical analysis, preprocessing (macros and the like), parsing, generation, optimization, and more. Some compilers, most I imagine, make multiple passes over the data, so yes, in a sense you are taking some of the same steps as a compiler. As for the .Net compiler using reflection, I'm not sure if it does or not. That would be an interesting topic of research. – Maurice Reeves Dec 14 '12 at 05:38
  • 1
    As for C++, I'd need to see more about what you're doing to really think about how to handle it. Obviously you'd want to make use of templates, and template meta-programming, but beyond that, yes, you'd probably need to pass some additional information in a data packet of some sort to let you know how to approach your user-defined objects. As for C? I haven't used classic C in forever, so I'm not the best person to ask. – Maurice Reeves Dec 14 '12 at 05:42
  • I was actually looking for specific patterns that abstract out this concept of yours. Do you know of any? In any case thanks for the awesome info. – Raghavendra Kumar Dec 14 '12 at 05:43
  • At this late point in the evening, nothing comes to mind, but if I think of anything over night while I sleep, I'll come back and add more. Also, if you're satisfied with my answer, could I trouble you to mark my answer as accepted when you get a chance? Best of luck, and let me know how it goes. – Maurice Reeves Dec 14 '12 at 05:45
  • Done. Is there a way to send you the detailed description of the application i'm working on? SO is prompting me to move this discussion to the 'chats'. – Raghavendra Kumar Dec 14 '12 at 05:49
2

You can also pick up ZeroMQ, which is a lightweight MQ software, enabled the communication between applications. ZeroMQ includes only 1 dll, and you can embedded in any of your applications.

ZeroMQ has all kind of client, include C, C++, .NET, Python, Java,Ruby ,and can run in both Windows/Linux/OSX..

ray_linn
  • 1,382
  • 10
  • 14