Archived

This forum has been archived. Please start a new discussion on GitHub.

Client Prox Partial Interfaces

The Slice C-Sharp compiler outputs partial interfaces for slice defined interfaces. For the subsequent compiler generated proxy interfaces, the partial keyword is not generated. This makes adding custom functionality to the proxy interface definitions (custom attributes in particular) impossible. The generated PrxHelper classes are also not marked as partial so I cannot decorate those types either.

Am I missing any way of forcing the C-Sharp compiler to generate the proxy interfaces with the partial keyword?

Thanks

Comments

  • benoit
    benoit Rennes, France
    Hi,

    The slice2cs compiler doesn't emit the partial keyword for proxies (only for classes/structs/exceptions and interfaces), we didn't expect users to extend the generated code for proxies using the C# partial mechanism. Could you tell us a bit more why you need this?

    A+
    Benoit.
  • Here is the use case:

    I would like to build a generic proxy resolver for client code. I want to write C# client code, something like:
    IServicePrx svcPrx = ServiceProxyFactory.BuildProxy<IServicePrx>();
    string result = svcPrx.GetStringResult();
    

    My servers that implement IServicePrx register themselves as well known using the IceGrid/Registry Admin interface.

    The ServiceProxyFactory that I'm building would be responsible for interacting with IceGrid/Query service in order to find the right type of Well Known IceObject and then build a proxy on behalf of the client. I don't want the client to know anything about IceGrid, locators, registry, etc... I only want them to have to know what kind of Proxy they are building represented in a C# interface, in this example IServicePrx.

    On the other hand, I want to build a generic Ice ServiceProxyFactory. I don't want the factory to know what kind of proxies it is building, only how to search for proxy types and create them. I want it to be able to build any type of IceObject proxy that it can locate using IceGrid.

    One potential way of doing this is via Reflection. If I can decorate the generated types in a partial interface definition, than I can decorate the types with additional information, which I can then reflect upon in my ServiceProxyFactory class. I can use that information to get the right Ice Type IDs, search for them and then to cast them back into the right interface that the client cares about.

    The current solution I have now is that I decorate the service interface that is defined in slice with additional information that describes the other types (Prx, Disp, etc...). Then I can use reflection to pull out a TypeID (from ice_staticId()) and then I build the right type of ObjectPrxHelperBase also using reflection. I think copy the ObjectPrx I got back from the query into properly typed one. This works but overly complicates the client code for a couple reasons.

    I fear this could be unclear but I hope not. I'm not seeing a simpler way of implementing this type of behavior. Hopefully I'm missing some type of generic Proxy Factory provided in the Ice library itself.

    Thanks-
    Benoit
  • benoit
    benoit Rennes, France
    Hi,

    There's no generic proxy factory in the Ice core. To cast proxies to your service proxies, Ice provides static uncheckedCast and checkedCast methods on the generated proxy helper class. You could use those methods instead of depending on Ice internals and the generated code to create the proxies. For example:
    public delegate T CastMethod<T>(Ice.ObjectPrx proxy) where T : Ice.ObjectPrx;
    
    private static T BuildProxy<T>(CastMethod<T> cast, string typeId) where T : Ice.ObjectPrx
    {
          Ice.ObjectPrx prx = _query.findObjectByType(typeId);
          return cast(prx);
    }
    
    // Usage
    HelloPrx hello = BuildProxy<HelloPrx>(HelloPrxHelper.uncheckedCast, HelloPrxHelper.ice_staticId());
    if(hello != null)
    {    
        hello.ice_ping();
    }
    

    With C# reflection, you could simplify it even more:
    public static T BuildProxy<T>() where T : Ice.ObjectPrx
    {
        System.Type t = typeof(T);
        Type helper = Type.GetType(t.FullName + "Helper");
        string typeId = (string)helper.GetMethod("ice_staticId").Invoke(null, null);
        Ice.ObjectPrx prx = _query.findObjectByType(typeId);
        return (T)helper.GetMethod("uncheckedCast").Invoke(null, new Object[] { prx });
    }
    
    // Usage
    HelloPrx hello = BuildProxy<HelloPrx>();
    if(hello != null)
    {    
        hello.ice_ping();
    }
    

    Cheers,
    Benoit.