When should we pass a Value and when should we pass a Type to the constructor of ObjectParameter and why?
When attempting to get a SQL OUTPUT value out of a stored procedure, it does not appear to make a difference passing a value of 0,1,2 etc or typeof(long) for example.
var ob = new ObjectParameter("CustomerID", typeof(long));
// or new ObjectParameter("CustomerID", 0)
// both work
db.InsertCustomer(ob, "CustomerName");
var CustomerID = ob.Value;
It depends on the information you have available when you are calling the constructor. All 3, name, value and type, are available as properties of the object and can be set later in the code.
It is possible that you need to create the parameter object, you know the name, and type, but you may have the value at a later time. In that case you can call the ObjectParameter(String, Type) constructor.
If you have the name and value when creating the object, then ObjectParameter(String, Object) could be more useful.
var ob = new ObjectParameter("CustomerID", typeof(long));
var ob2 = new ObjectParameter("CustomerID", 0);
Shouldn't be the same as one is an int and one is a long.
In your case, where you are getting data out, it won't matter if you use a type of a value. However using a type makes it more verbose, easier to read, and easier to understand in my opinion. It can prevent any mistakes such as int vs long.
Related
Imagine that you want to declare an object with an anonymous type, but you need it to be generic (I can't think of an actual reason why, this is theoretical). How would you create such an object?
For example:
var anonymousGeneric = new <T>{ }; // <- doesn't work
var anonymousGeneric = Activator.CreateInstance((new { }).GetType()); // Not generic
edit:
// because:
(new { }).GetType().IsGenericType == false
// Of course, any useful anonymous object _will_ be generic:
(new { a="b" }).GetType().IsGenericType == true
// But in the process of testing various aspects of this question
// it had never occurred to me that I needed to supply any property
// (this was all theoretical, remember)
end edit
But neither of those works. Of course, the real-world solution to this imagined problem is to define an actual class definition:
public GenericThing<T> { }
But that isn't anonymous like above.
Once the object is created, imagine using it later on with something like:
var anonymousGenericType = anonymousGeneric.GetType();
// These throw exception
// <>f__AnonymousType0#1 is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true.
// + System.RuntimeType.MakeGenericType(System.Type[])
var intThing = anonymousGenericType.MakeGenericType(typeof(int));
var stringThing = anonymousGenericType.MakeGenericType(typeof(string));
In summary, is it possible to create an anonymous generic object?
(I can't think of an actual reason why, this is theoretical)
In that case, let's stick with the simple and obvious, since it's easier to find a reason: simply create a regular anonymous object from a generic method.
public object Foo<T>(T t) { return new { t }; }
Here, Foo(0) and Foo("") will necessarily return different types, but they'll still share a type definition.
Pretty much any use of anonymous types can make equal sense inside a generic method.
anonymousGeneric.GetType() is returning the wrong type of generic type: Closed (with type parameter(s)) vs open (without)1. If you want to change a type parameter, you need to get the generic type definition from it.
The following actually works, though I can't imagine what good it does anybody 2:
var anonymousGeneric = new {a = "b"};
var anonymousGenericType = anonymousGeneric.GetType().GetGenericTypeDefinition();
var intThingType = anonymousGenericType.MakeGenericType(typeof(int));
var intThingInstance = Activator.CreateInstance(intThingType, 9);
Now we have a thing just like anonymousGeneric, but its type parameter is int instead of string, and its a property is 9. But what's it good for? How do you declare a reference to it? You could bind to its properties in XAML, if you had some time on your hands.
1 Thanks to Amy and Servy for pitching in to clear up my confusion with terminology.
2 Note that there are more things in heaven and earth than are dreamt of in my philosophy.
I have an initial snippet which deserealized parameters, checks for value and handles the error:
var param = js.Deserialize<int?>(jqData.Params);
if (param.HasValue)
{
resp.ReturnValue = param.Value;
}
else
{
//handle error code
}
Now, during my modification, I have changed the method to accept a list of class parameters instead of nullable integers
var param = js.Deserialize<ClassName>(jqData.Params);
Now it invalidates .HasValue and .Value methods.
My question is: How do I properly modify these two lines so it would hold the same meaning as initial if statement?
Thus far I only thought about switching to if (param != null), but I cannot think of proper equivalent to .Value.
As soon as ClassName is a class (see - a reference type) you just need to check if it is not null.
If it is not - then the variable holds a reference to an object that you use as-is.
How can I apply the query options on a non clr type. The .ApplyTo method is throwing an error when I'm using it.
Error:
"The query option is not bound to any CLR type. 'ApplyTo' is only
supported with a query option bound to a CLR type."
var x = (EdmCollectionType)Request.GetODataPath().EdmType;
ODataQueryContext queryContext = new ODataQueryContext(Request.GetEdmModel(), x.ElementType.Definition);
ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, Request);
//codes.....
queryOptions.ApplyTo(Products);
Just as the error said, the query options can't be applied on a non clr type now.
It is because now webapi need the clr type to generate linq expression for query options.
However you can implement the ApplyTo function on a non clr type yourself with the raw values in the query options:
queryOptions.Filter.RawValue
queryOptions.OrderBy.RawValue
...
ODataQueryContext queryContext = new ODataQueryContext(Request.GetEdmModel(), x.ElementType.Definition);
In the above line, we need to explicitly pass the Class Type obj to ODataQueryContext.
Let's assume a type named A which has been created at runtime.
Type a = //Get the type at runtime ;
ODataQueryContext queryContext = new ODataQueryContext(Request.GetEdmModel(), a);
This should resovle the exception.
Now, come to ApplyTo() we can pass an instance of type A to it.
object instance = Activator.CreateInstance(a);
odataQuerySetting.ApplyTo(instance,, new ODataQuerySettings() { });
However, we would like to run ApplyTo() against a list of objects as well as one instance.
Array class could help us to accomplish this. Suppose we need to create 10 instances:
Array values = Array.CreateInstance(a, 10);
for (int i = 0; i < 10; i++)
{
values.SetValue(Activator.CreateInstance(t), i);
}
Needless to say that we can add properties to our instances as we would like to and then pass it to SetValue().
Finally, the ApplyTo() can be executed against our list as follow:
queryOptions.ApplyTo(values.AsQueryable());
Note: if you get the status:406 then one possible cause could be the JsonFormat. use a custom MediaTypeFormatter to resolve that.
I hope that this might help someone.
If I have this string list:
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
in which:
- MyObject: the object class
- SetWidth: the property of the object
- int: type of the SetWidth is int
- 10: default value
- 0: object order
- 1: property order
Then how can I construct an object like this:
[ObjectOrder(0)]
public class MyObject:
{
private int _SetWidth = 10;
[PropertyOrder(1)]
public int SetWidth
{
set{_SetWidth=value;}
get{return _SetWidth;}
}
}
So, I would like have something like this:
Object myObject = ConstructAnObject(myObjectString);
and the myObject is an instance of MyObject. Could it be possible in C#?
Thanks in advance.
I think you better use the Object Serialization/Deserialization instead of creating a custom method that basically needs to do the same thing
more info at:
http://msdn.microsoft.com/en-us/library/ms233843.aspx
Here is some quick and dirty code to get you started:
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
var info = myObjectString.Split(',');
string objectName = info[0].Trim();
string propertyName = info[1].Trim();
string defaultValue = info[3].Trim();
//find the type
Type objectType = Assembly.GetExecutingAssembly().GetTypes().Where(t=>t.Name.EndsWith(objectName)).Single();//might want to redirect to proper assembly
//create an instance
object theObject = Activator.CreateInstance(objectType);
//set the property
PropertyInfo pi = objectType.GetProperty(propertyName);
object valueToBeSet = Convert.ChangeType(defaultValue, pi.PropertyType);
pi.SetValue(theObject, valueToBeSet, null);
return theObject;
This will find the MyObject, create an object of the proper propertytype, and set the matching property.
If you use C# 4.0, you can use the new dynamic feature.
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
String[] properties = myObjectString.Split(',');
dynamic myObj;
myObj.MyObject = (objtect)properties[0];
myObj.SetWidth = Int32.Parse(properties[1]);
// cast dynamic to your object. Exception may be thrown.
MyObject result = (MyObject)myObj;
I don't quite understand why do you need ObjectOrder and PropertyOrder... Once you have their names you probably don't need them, at least for "deserialization"...
Or please advice what is their role?
You definitely can simply do it via reflection:
Split the string by comma (using myString.Split)
Use reflection to find an object within your application:
Find the type with name = splittedString[0] (enumerate all the assemblies within the domain and all the types within each assembly);
Instantiate the type found (using Activator.CreateInstance)
Find the property by name (Using objectType.GetProperty)
Set the property value (using propertyInfo.SetValue)
Return the object
Assuming you need to generate new types there are two possible ways to do so:
Using Reflection Emit
Using CodeDom provider
I think the simpler solution is CodeDom provider. All needed is to generate the source as a string in memory, and then compile the code and instantiate a new instance with Activator. This is a nice example I just found.
The reason I think that CodeDom provider is simpler is that it has shorter setup - no need to generate dynamic module and assembly and then work with type builder and members builder. In addition, it doesn't require working with IL to generate the getter and setter bodies.
An advantage that reflection emit has is performance - dynamic module can add more types to itself even after one of the types was used. CodeDom provider requires creating all the types at once, otherwise it creates a new assembly each time.
i've got the following in C#:
string typename = "System.Int32";
string value = "4";
theses two strings should be taken to generate an object of the specified type with the specified value...
result should be:
object o = CreateUnknownType(typename, value);
...
Int32 test = (Int32)o;
Is this what are you are thinking?
object result = Convert.ChangeType("4", Type.GetType("System.Int32"));
As stated, this is too broad and can not be solved generally.
Here are some options:
Type type = Type.GetType(typename);
object o = Activator.CreateInstance(type);
This will create an instance of the type that typename is describing. It calls the parameterless constructor of that type. (Downside: Not all objects have a parameterless constructor. Further, this does set the state of the object using value.)
Type type = Type.GetType(typename);
object o = Activator.CreateInstance(type, new[] { value });
This will create an instance of the type that typename is describing. It calls a constructor of that type that accepts one parameter of type string. (Downside: Not all objects have such a constructor. For example, Int32 does not have such a constructor so you will experience a runtime exception.)
Type type = Type.GetType(typename);
object o = Convert.ChangeType(value, type);
This will attempt to convert the string value to an instance of the required type. This can lead to InvalidCastExceptions though. For example, Convert.ChangeType("4", typeof(FileStream)) will obviously fail, as it should.
In fact, this last example (create an instance of type FileStream with its initial state determined by the string "4") shows how absurd the general problem is. There are some constructions/conversions that just can not be done.
You might want to rethink the problem you are trying to solve to avoid this morass.
Creating an instance of a type you know by name (and which should have a default constructor):
string typeName = "System.Int32";
Type type = Type.GetType(type);
object o = Activator.CreateInstance(type);
Parsing a value from a string will obviously only work for a limited set of types. You could
use Convert.ChangeType as suggested
by PhilipW
or maybe create a
Dictionary<Type,Func<string,object>>
which maps known types to known parse
functions
or use reflection to invoke the
Parse(string) method on the type,
assuming there is one:
string valueText = "4";
MethodInfo parseMethod = type.GetMethod("Parse");
object value = parseMethod.Invoke(null, new object[] { valueText });
or maybe you can use the
infrastructure provided by the .NET
component model. You can fetch the
type converter of a component and use
it like this:
TypeConverter converter = TypeDescriptor.GetConverter(type);
object value = converter.ConvertFromString(valueText);
Your logic seems a little flawed here. Obviously, if you're directly casting the object at a later time to the actual type it is, then you must know the type to begin with.
If there's something else that is missing from this question please elaborate and maybe there is a more appropriate answer than simply, "This doesn't make much sense."
Perhaps you have a set of different types, all of which implement a known interface?
For example if you have several different user controls and want to load one of them into a container, each one might implement IMyWobblyControl (a known interface) yet you might not know until runtime which of them to load, possibly from reading strings from some form of configuration file.
In that case, you'll need to use reflection to load the actual type from something like the full assembly name, then cast it into your known type to use it.
Of course, you need to make sure that your code handles invalid cast, assembly not found and any of the other exceptions that are likely to come along through something as wobbly as this...
This seems like a job for Int32.Parse(string). But to agree with the others it seems this is "unique" and one should probably think gloves.
Here's a specific example of the problem involving Azure SQL Federations...which splits data into separate db's according to a key range.
The key range types are:
SQL / .Net SQL type / CLR .Net
INT / SqlInt32 / Int32, Nullable
BIGINT / SqlInt64 / Int64, Nullable
UNIQUEIDENTIFIER / SqlGuid /Guid, Nullable
VARBINARY(n), max n 900 / SqlBytes, SqlBinary /Byte[]
Ideally, a C# function param could take either .Net SQL type or CLR .Net type but settling on just one category of type is fine.
Would an "object" type param be the way to go? And, is there a feasible way to identify the type and convert it accordingly?
The concept is something like:
public void fn(object obj, string fedName, string distName, bool filteringOn)
{
...figure out what type obj is to ensure it is one of the acceptable types...
string key = obj.toString();
return string.Format("USE FEDERATION {0} ({1}='{2}') WITH RESET, FILTERING = {3}", fedName, distName, key, (filteringOn ? "ON" : "OFF"));
}
Though the param value is cast to string, it will be recast/checked on the sql server side so validating it on the app side is desired.
After using:
Type type = Type.GetType(typename);
Try this extension method:
public static class ReflectionExtensions
{
public static T CreateInstance<T>(this Type source, params object[] objects)
where T : class
{
var cons = source.GetConstructor(objects.Select(x => x.GetType()).ToArray());
return cons == null ? null : (T)cons.Invoke(objects);
}
}
Hope this helps.