How to pass var to function in C# - c#

How I can pass var to function?
I need to create the following unknown data model, and pass it to my function, which shout parse it using RazorRenderer:
var emailData = new {name="value" , name2="value2" ... , nameN="valueN"}
The function can't receive var, so we used object, but then we can't convert it back, and we get an exception when call:
string htmlBody = render.Parse(File.ReadAllText(TemplatePath), emailData );
When I do the following, in same function it works:
var emailData = new { UserRequest = "hello", UserEmail = "name#domain.com" };
string htmlBody = render.Parse(File.ReadAllText(TemplatePath), emailData);
But when try to pass the emailData to the function it not work, any idea?
I can do the rendering out of the function and pass the result to the function, but I thought it may be nice to do it internally inside the function.
BTW- I tried JSON Serialize and Decerialize, with no luck.

If I understand your question correctly, it is not possible. Anonymous type names cannot be represented in user code hence there is no way to make them an input parameter to a function.
Your best bet is to create a type and use that as the return from the query and then pass it into the function. For example,
class YourDataClass {
public string ColumnName;
}
var query = (from name in some.Table
select new YourDataClass { ColumnName = name });
YourMethod(query);
...
YourMethod(IEnumerable<YourData> enumerable);
In this case though, you are only selecting a single field, so it may be easier to just select the field directly. This will cause the query to be typed as an IEnumerable of the field type.

Related

How to get GridLookup with complex name

I'm trying to get GridLookup selected value,
#Html.DevExpress().GridLookup(settingsGrid =>
{
settingsGrid.Name = "CommandeDetailEnCours.Compte";
settingsGrid.KeyFieldName = "Numero";
[...]
}).BindList(Model.ListeComptes).Bind(Model.CommandeDetailEnCours.Compte).GetHtml()
The question is: How I can get Value because in javascript
"CommandeDetailEnCours.Compte".GetGridView() [...]
not work ?
Use the client-side GetValue method in the following manner.
To retrieve the complex name on the client use the How to use the ClientInstanceName and Name properties when they contain special characters approach.
var lookupClientInstance = ASPxClientControl.GetControlCollection().GetByName("CommandeDetailEnCours.Compte");
var value = lookupClientInstance.GetValue();
alert(value);

Newtonsoft JSON Deserialist into list of Type

I am dealing with JSON returned from an API, and am trying to compress the code required to deserialise it.
for a single record,
im passing in an "object", ReturnOBJ.
public object getAPIRecord(object returnOBJ, string recordReference)
{
string TypeName = ReturnOBJ.GetType().ToString();
Type t = Type.GetType(TypeName);
//code getting string back from API
returnObject = JSONConvert.DeserializeObject(JSONfromAPI, t);
return returnObject;
}
the above works, in a function returning an Object, which i'm then casting into what i need in my functional code.
I'm calling the above as:
ContentClass newContent = new ContentClass();
newContent = (ContentClass)getAPIRecord(newContent, "WC/123");
so the function is deriving "ContentClass" as the type from the object passed in.
however, if the JSON coming back is returning a list/array of type "t", how do i get it to work?
my brain was thinking something along the lines of
List<object> returns = JsonConvert.DeserializeObject(JSONfromAPI, List<t>);
but it flags the List as "not valid in the given context".
i'm guessing my List could also be wrong. I'm not used to working with Type at all, but im trying to streamline my code for handling API responses.
i'd like to be able to call it such:
List<ContentClass> newlistOfContent = new List<ContentClass>();
newlistOfContent = getListofAPIRecords(newListOfContent, APIPArameters);
what do i need to do to morph my single record return into a List return?

Convert Class Name Variable to Class Type c#

I am implementing web api methods to return some data. It works fine until we want to introduce new parameter to determine whether we should return Extra Detail of the Offering or just the normal detail.
My original code is like the following:
using (IDbConnection conn = _context.Database.GetDbConnection())
{
var parameters = new
{
CourseName = model.query,
CourseType = model.CourseType,
other parameters....
};
var obj = await conn.QueryAsync<Offering> ("SearchOfferings", parameters, commandType: CommandType.StoredProcedure);
if (obj == null)
return NotFound("Record not found");
return new ObjectResult(obj);
}
I am using DAPPER to execute the stored procedures.
Now, we have added Extra parameter from querystring and added the logic to the existing code. If Extra = True, we want to return FullDetail with Different Object Type. otherwise, return only the Brief data.
I would like to know how can I pass the objectToReturn value in QueryAsync (dynamic param) method?
string objectToReturn = string.Empty;
if (extra)
objectToReturn = "Offering";
else
objectToReturn= "BriefOffering";
var obj = await conn.QueryAsync<**objectToReturn**> ("SearchOfferings", parameters, commandType: CommandType.StoredProcedure);
When the client can change the query parameters in order to get detailed offerings then it might as well just access a different resource exposing your detailed offerings instead.
Suppose your current REST API resource for the offerings is:
http:\server.com\offerings\{id}
Why not have a second one like:
http:\server.com\detailedOfferings\{id}`
This makes your REST interface easier to use and understand while also simplifying the implementation.
If you really want to stick to the query parameter switch then you can just make a conditional call to one of the two generically typed methods:
if (extra)
return await conn.QueryAsync<Offering>(
"SearchOfferings", parameters, commandType: CommandType.StoredProcedure);
else
return await conn.QueryAsync<BriefOffering>(
"SearchOfferings", parameters, commandType: CommandType.StoredProcedure);
Dapper does have alternate Query / QueryAsync method signatures that might help you - there is one that will return a set of objects where each object is a type that is specified via a method argument rather than a generic type parameter.
This would allow you to do something like this:
var typeToReturn = Type.GetType("MyProject.Entities.Offering");
var obj = await conn.QueryAsync(
type: typeToReturn,
sql: "SearchOfferings",
param: parameters,
commandType: CommandType.StoredProcedure
);
The type name must be the full name of the desired type, so if the QueryString value was going to specify only "Offering" then you would have to know what namespace that that entity would be in and change the code to something like
var nameOfType = "Offering";
const string entityNamespace = "MyProject.Entities";
var typeToReturn = Type.GetType(entityNamespace + "." + nameOfType);
var obj = await conn.QueryAsync(
type: typeToReturn,
sql: "SearchOfferings",
param: parameters,
commandType: CommandType.StoredProcedure
);
Of course, having the return type be IEnumerable<object> means that you can't easily do much directly with the returned data but that was always going to be the case if you wanted to write some code to return dynamically-typed code; you wouldn't know at compile time what types were going to come back. If you're just going to serialise it to JSON, for example, then that's no big deal.
I just wanted to add this answer since it directly addresses what you asked - but I do also agree with Sam C's comment that you might be better using the method signature that returns IEnumerable<dynamic> if you honestly don't care about what types are returned.

How to treat function as string?

just I want to ask is it possible to Call function as ToUpper or ToLower() as string for example f.Name.Replace(" ", "_").ToLower()".ToLower()" or "ToUpper" for example if user select convert file name to ToLower() from dropdown list.it will take the value 'ToLower' and added to in of the function and executed the function call
Well, not cleanly. You could use reflection to find the method but you'd have to know the exact type that the function will be applied to since you won't get sophisticated binding like you do at compile-time. Plus you'll be limited to one method signature (in this case, no input parameters and returns a string).
To support any string function with that signature you could use:
string val = f.Name.Replace(" ", "_").ToLower();
string strCommand = "ToUpper";
MethodInfo theMethod = typeof(string).GetMethod(strCommand,new Type[] {});
string result = (string)(theMethod.Invoke(val,null));
But a simple switch seems cleaner and safer here.
The conditional operator (?:) would probably be a better option here
var fileName = f.Name.Replace(" ", "_");
fileName = ddl.SelectedValue == "ToLower" ? fileName.ToLower() : fileName.ToUpper();
Using Reflection for something as trivial as this is pretty unnecessary.
If you know the methods you want to call before, you can register them in a dictionary (key = name of the function or something user friendly, value = function that performs the conversion):
var dict = new Dictionary<string, Func<string, string>>();
dict.Add("Lowercase", x => x.ToLower());
dict.Add("Uppercase", x => x.ToUpper());
You can bind the drop down list to the dictionary (text = Key, value = Value) and perform the conversion as follows (ddl is the name of the DropDownList):
var f = (Func<string, string>)ddl.SelectedValue;
var convStr = f(inputStr);
You can create a defined dictionary of functions, which you can access by name of the action. You will get rid of any conditional statements and of all reflection. Example is given below:
var actions = new Dictionary<string, Func<string, string>>()
{
//keys may have other, human-readable values
{"ToLower", s => s.ToLower()},
{"ToUpper", s => s.ToUpper()}
};
//you will receive this from drop down list, it's the name of the action
var userSelectedOption = "ToUpper";
//string that you want to process
var myString = "some other user input";
//selecting appropriate action and passing myString to it
var transformedString = actions[userSelectedOption](myString);
//prints "SOME OTHER USER INPUT"
Console.WriteLine(transformedString);
Using reflection, you can call a methods using a string:
String ToLower = "ToLower";
String SometString = "This Is My String";
Type stringType = typeof(String);
// Get the overload of ToLower that takes no parameters
MethodInfo method = stringType.GetMethod(ToLower, System.Type.EmptyTypes);
// Invoke the method with no parameters
String newString = (String)method.Invoke(SometString, null);
MessageBox.Show(newString);
If I have understood your question correctly, you want to call a method based on a string.
You can use reflection, which is a topic in and of itself, but to get you started you can do something like:
MethodInfo chosenMethod = typeof(string).GetMethod(methodName, Types.EmptyTypes);
chosenMethod.Invoke(stringToModify, new object[]{});
But if it is a very limited set of functions you want to expose, you should just do a switch statement over the user input:
switch(methodName)
{
case "ToLower":
stringToModify.ToLower();
break;
...
You can use a simple switch statement:
switch (value) // Assuming value is of type SomeEnum
{
case SomeEnum.ToLower:
return f.ToLower()
case SomeEnum.ToUpper:
return f.ToUpper();
default:
//Do the Default
break;
}
This is how you parse what you get from the UI:
public static T ParseEnum<T>( string value )
{
return (T) Enum.Parse( typeof( T ), value, true );
}
Perhaps you might need to avoid limitations is sort of a Runtime intepreter of C#, like eval() function in JavaScript, which is not easily nor trivial to implement, but there is a good library out there called C# Eval ( http://csharp-eval.com/Download.php ) that uses Reflection internally of course. It is heavier but more effective for this, or even for much more complex escenarios.
You might use it in this way for example:
class Person
{
public string Name;
public string Process(string expression)
{
return CsEval.Eval(this, expression);
}
}
And then might call it:
var f = new Person();
f.Name = "John";
f.Name = f.Process("Name.Replace(" ", "_").ToLower()");
Of course this is just an example of how it evaluate what is in the string, as you can see you just need to pass a "context" where the expression is going to mean something, which in this case is the current class ("this").

Extension method with dynamic named parameters

I'm currently writing an extension to replace the normal string.Format with my FormatNamed-function.
So far I have got this code, but I want to change the way to input the parameters
void Main()
{
string sql = "SELECT {fields} FROM {table} WHERE {query}"
.FormatNamed(new { fields = "test", table = "testTable", query = "1 = 1" });
Console.WriteLine(sql);
}
public static class StringExtensions
{
public static string FormatNamed(this string formatString, dynamic parameters)
{
var t = parameters.GetType();
var tmpVal = formatString;
foreach(var p in t.GetProperties())
{
tmpVal = tmpVal.Replace("{" + p.Name + "}", p.GetValue(parameters));
}
return tmpVal;
}
}
Not the prettiest of replaces, but it does the job.
Anyway. I want to change so I can execute it with
.FormatName(field: "test", table: "testTable", query: "1 = 1");
Is there any way I can do this? I have tried googling for dynamic named parameters with no good results.
You won't be able to specify an arbitrary number of dynamic, named parameters. that's just not something that C# supports. Your existing code seems okay to me, although I don't see the need for the dynamic parameter. This will work just as well:
public static string FormatNamed(this string formatString, object parameters)
{
var t = parameters.GetType();
var tmpVal = formatString;
foreach(var p in t.GetProperties())
{
tmpVal = tmpVal.Replace("{" + p.Name + "}", p.GetValue(parameters));
}
return tmpVal;
}
And then calling it as:
string sql = "SELECT {fields} FROM {table} WHERE {query}"
.FormatNamed(new { fields = "test", table = "testTable", query = "1 = 1" });
Although I really wouldn't advise using this sort of method for constructing SQL (it won't save you from SQL injection attacks at all), the method itself is sound.
I have tried googling for dynamic named parameters with no good results
That's because the capability does not exist. Think about it - how would the function know what to do if the parameters and their names were not known at compile time? The closest thing I can think of is using params which gives you an array of values, but they must all be the same type, and you can still access them by a given name (and index value).
I'd stick with the method you're currently using:
.FormatName(new {field = "test", table = "testTable", query = "1 = 1"});
That creates an anonymous type with the properties specified, which should work fine with your existing code. Plus it's only a few extra characters to type.
Also note that dynamic doesn't buy you anything here since it's used to access properties directly without using reflection. Since you're using reflection to get the propeties you can just use object.

Categories

Resources