We are using a Microsoft ERP which dynamically exposes web services. The services generated by the service is out of our control. We have no say so in how the objects, including the type definitions, are created and exposed. When a new method is added or removed from the web service, all of the type enumerations are renumbered and everything that uses the web service, after updating to the new definitions, is hosed up. So essentially,
enumeration Type1
Item1
Item2
Item3
... could become
enumeration Type6
Item1
Item2
Item3
...with the enumeration type name changing, but members of the type remaining static. The service outputs a service which looks exactly like the end result of using the XSD.exe to generate objects. So anytime someone exposes a new method on the service (via the ERP GUI), the objects are rebuilt, types are assigned to the service definitions in alphabetical order, reexposed, leaving the entire code base shot.
I attempted to use reflection to determine the type and then parse out the static member into the new business object, but it doesn't work because I can't type cast the enumeration without knowing the actual name of the type. The following won't work.
System.Type t = service.BusinessObjectEnumeration.GetType();
service.SomeField = Enum.Parse(t,"Item1");
...as the compiler throws an error because I'm not explicitly casting the enumeration.
Any ideas how I can overcome this issue while dynamically casting the type to the correct enumeration?
Again, I cannot modify the actual objects exposed by the service, only the code subscribing to the service.
Re the example code:
System.Type t = service.BusinessObjectEnumeration.GetType();
service.SomeField = Enum.Parse(t,"Item1");
Maybe the way to do this is via reflection:
var prop = service.GetType().GetProperty("SomeField");
prop.SetValue(service, Enum.Parse(prop.PropertyType, "Item1"), null);
I had a similar issue with Nav web services. The solution I used to to create a new web reference for each service you expose through Nav rather than just a single one for all services. This prevents the name collisions you are experiencing without using reflection or hacks.
Why should you need to parse things?
If I understand Enums correctly, they pass on the value (and not the Enum itself).
EDIT: What I mean is, enum is not same as a class. For a class, one expects an instance to be passed/received. For an enum, it is one or combination of its members, which is passed in form of an int value.
EDIT2: Are you trying to use the enum as some kind of struct here?
EDIT3: You will have to see what type is the enum in debug mode, to figure out how to reflect on it.
object enumValueReturned = service.BusinessObjectEnumeration;
Put the enumValueReturned in watch window & play with it using reflection (GetMembers) to see, how would you reach Item1.
Related
Unity supports resolve based on types
T obj = container.Resolve<T>("id");
that means without knowing T, I can not resolve, I am writing some extension methods for my unity container where I want to add Resolve method which would return object type.
object obj = container.Resolve("id");
because when registering I already know T so I can keep type in a dictionary with "ID". This is unreliable as unity can itself resolve some types(even when not registered) Is there a simpler and reliable way to do resolve using only the Id for resolving?
This is diffrent from calling generic method from reflection due to performance issues and also since the resource is already registered with unity for DI hence i want to use existing solution to keep it consistent.
Now if i can resolve something by ID and return object or dynamic i can use type converters internally to convert it to expected type later. Upfront i do not know type which has to be used.
If object is your interface, you can use that, of course:
container.RegisterType<object, ObscureService>( "service" );
container.RegisterType<object, SecretPlugin>( "plugin" );
object unknown = container.Resolve<object>( "service" );
object anotherUnknown = container.Resolve<object>( "plugin" );
This has very limited (sensible) use, though. I'd say you should only use this if you act on direct request from the user and the resolved unknown is some kind of view model that's only used to be presented back to the user.
If code requests the object, there's no reason why that code should not somehow be able to know what it's requesting.
I'm working with pre-defined IOrganizationService object I cannot modify — it's out of my control.
And it seems to be by default this IOrganizationService returns resolved types as if EnableProxyTypes() was called implicitly somewhere on originating OrganizationServiceProxy.
And this ruins all business logic, since early bound entities could not be serialized that easily, since on different installations they could be resolved to different types. So even if they would be successfully serialized, cannot be 100% certain that they could be de-serialized.
To be more specific it's plugin for XrmToolBox. If hosting application loaded plugin that uses early bounding, these generated types will be discovered via reflection and applied to results of Retrieve and RetrieveMultiple calls.
For example RetrieveMultiple to account entity response will normally contain Entity[], each item of this array will have LogicalName property set to account.
But if early bound types was discovered in assembly, let's call it EarlyBouldLibrary.dll, the same RetrieveMultiple will return EarlyBouldLibrary.Account[]. Each item of this array will be derived from Entity and will contain same field as in first example, but with additional properties.
The problem is in following. If we will try to serialize EarlyBouldLibrary.Account[] to XML it will fail. Because EarlyBouldLibrary.Account is unknown.
Ok, it's possible to add types to known. But there is no guarantee, that one day another early bound types will be found in NewEarlyBouldLibrary.dll... And they will have name NewEarlyBouldLibrary.Account... Which is unknown...
Ok, let's assume serialization succeeded, no matter which types are referenced EarlyBouldLibrary.Account or NewEarlyBouldLibrary.Account, but if we will try to de-serialize, on environment where these early bound libraries not present... action will fail.
So only way will be not to use specific early bound types, that out of our control, and use standard and safe Entity. But it's impossible while system automatically resolves proxy types.
So, question: is there any way to disable resolve of early bound types?
You can redirect your proxy to another assembly containing the types you need (or even containing no early bound types at all).
The example below resets the proxy assembly:
private void ResetProxyAssembly(IOrganizationService service)
{
var serviceProxy = (OrganizationServiceProxy) service;
serviceProxy.EnableProxyTypes();
}
In certain scenarios this may not work. Instead you can explicitly select the desired proxy assembly:
private void ResetProxyAssembly(IOrganizationService service)
{
var serviceProxy = (OrganizationServiceProxy) service;
serviceProxy.EnableProxyTypes(typeof(MyEarlyBoundEntity).Assembly);
}
Could you add [assembly: Microsoft.Xrm.Sdk.Client.ProxyTypesAssembly] to the AssemblyInfo file of the EarlyBouldLibrary.dll or NewEarlyBouldLibrary.dll assembly?
So, I'm using the XML Type Provider to create types from an XML document.
One of the elements in the XML file has a Date property:
<Edit Date="06/30/2015 16:57:46"
... />
Which of course results in a Type like this:
type Edit =
inherit XmlElement
member Date: DateTime
...
Is there a way that I can add the following code:
member this.LocalTime
with get() =
this.Date.ToLocalTime()
To the resulting Edit type?
The reason for this is that I'm binding to instances of Edit from XAML and I really don't want to write an IValueConverter just to do that.
Edit:
So, I just realized that these types do not make it to my XAML. Instead, I get instances of FSharp.Data.Runtime.BaseTypes.XmlElement which of course do not even contain the properties I see in F# code. I also need to consume these types from C# code, and even there I get only XmlElements without the properties
I know I could use XPath in XAML to navigate the XElements inside this, but I still need a way to access the resulting object model in a strongly typed way, both from C# and XAML.
Edit2:
So now I wrote a Type Extension like this:
type Catalog.Edit with
member this.LocalTime with get() = this.Date.ToLocalTime()
And I see the member in F# code just like the generated members. However there's 2 drawbacks to this approach:
1 - It forced me to change my namespace into a module, which is less convenient since these types are all consumed from C# code and in there I see them as nested classes into the module class, which is ugly.
2 - I still can't see this member (nor the generated ones) from either C# nor XAML.
What's the correct way to implement this in the described scenario?
The F# Data type providers for XML and JSON are erasing type providers. This means that the types you see when you use them from F# do not actually exist at runtime - they are replaced with some underlying runtime representation (here XmlElement).
Unfortunately, this means that the types are not real types and so they are only visible to F#.
My recommendation is to define a simple domain type using F# records and load your data from the XML into your records. This is a bit more work, but it also gives you a bit more safety, because you are explicitly defining the structure - and so if your XML changes, you'll know you need to change your XAML code too!
It should be as easy as something like this:
type Edit = { Date : DateTime }
let GetData () =
let doc = MyXmlType.Load("somefile.xml")
seq { for item in doc.Edits -> { Date = item.Date } }
I need to cast like this:
/* Cast Brakets */
(Type.FromString(mystring))myObject.doSomething();
I need to get the type that I cast at runtime, in this particular case I can't use a generic "T" class or method.
Although if you had a way of changing the T-generic Type at runtime (without calling a class or method again) that would also help.
Here is a more specific version of my problem:
I have a List comboList and my GUI can add new ComboBoxes at runtime, these will automatically be put into comboList. Now there are database tables for each of those ComboBoxes in comboList. I added the name of each of the database classes in the .Tag field of each ComboBox
(example: combobox_users.Tag = "users_databaseClass")
Now at runtime I need to cast into the type of users_databaseClass for example, but it appears to me that this is impossible. It appears that this is simply not possible to put a Type into cast-brackets at runtime to actually cast that type.
Help would be greatly appreciated, I've been trying for days.
To use the properties and methods of a wacky type, you'll need a reference to that type (e.g. Type.GetType("string_name_of_type")) and you'll need some pretty cool reflection (e.g. theType.GetMethod("method_name")). Your performance won't be great. See http://msdn.microsoft.com/en-us/library/system.type.getmethod(v=vs.71).aspx
I created a WCF service.in my data contract I have two attributes lets say:
[DataMember]
Private User objUser;
and
[DataMember]
Private tempClass ObjTemp;
I have get and set property for both the attributes. In my implementation class, I have an object of datacontract class... lets say. objData.
When I assign
objData.ObjTemp=(function which return objTemp);
the service work fine. But, when I assign.
objData.objUser=(function which return objUser)
it throws following error:
The underlying connection was closed: The connection was closed
unexpectedly.
When I comment
objData.objUser=(function which return objUser)
it works fine again.
When I inspect the code inside my User class, I found one property creating problem. When I change the property that property it works fine too; but i do not know why that property is creating problem.
The property is like this:
public IPAddress IP { get; set; }
Now this IPAdress class contains a constructor, and get and set for ip variable. In the get, it simply returns ip variable.
in set it checks some condition and then assign value to ip variable. If condition fails, it throws an exception. Can anybody explain what the problem could be?
I just checked another thing.
If i remove [DataMember] attribute from private User objUser; it works fine; but if i put [DataMember] back it generates the same error.
any suggestions?
You will most likely find that objUser is not serializable. For more info read this: MSDN: Using Data Contracts
To quote a short snippet of that:
All .NET Framework primitive types, such as integers and strings, as well as certain types treated as primitives, such as DateTime and XmlElement, can be serialized with no other preparation and are considered as having default data contracts.... New complex types that you create must have a data contract defined for them to be serializable.
You could also consider using the Service Trace Viewer tool from Microsoft to help track down the exact problem you are having.
Edit:
if it is the System.Net.IPAddress object you are talking about, then it is marked as [Serializable], but it doesn't have a default parameterless constructor, which is one of the requirements necessary when using the DataContractSerializer (which is what is used to serialize your data objects over the WCF boundary). You may also want to ensure that if any of your custom objects used in your WCF calls contain any further custom objects (in properties, like your IPAddress) then they are decorated with the KnownType attribute.
So, as a solution you can either write your own IPAddress class that plays nice with the DataContractSerializer, or switch to using the XmlSerializer in your WCF calls.