I get an error when I try to cast a query. This is the code of the query:
var query = (from article in db.V_CLIENT_PRIX
where article.CLIENT == Current_Client_Id
select new
{
ID = article.ID,
ARTICLE = article.Article,
REFERENCE = article.Reference,
REMISE = article.Remise,
PRIXVHT = article.PrixVHT,
CLIENT = article.CLIENT,
}
);
And I cast it like this:
ConventionList articlelistconvention = new ConventionList();
articlelistconvention = (ConventionList)query;
This is the code of my model:ConventionList
public class Commandelist
{
public string ARTICLE { get; set; }
public string CIN { get; set; }
public decimal STOCK { get; set; }
public string REFERENCE { get; set; }
public decimal PRIXVHT { get; set; }
public string IMAGE { get; set; }
public double QUANTITE { get; set; }
}
Can someone help me fix it?
You might be coming from a language with duck typing, like Javascript; however, in C# this is not possible. You can typically only cast objects if the interfaces and/or inheritance allows you to do so. The dynamic object you create in your Linq query will not share ancestry with the object you're trying to cast to.
In your specific code example though there is a quick fix:
var query = (
from article in db.V_CLIENT_PRIX
where article.CLIENT == Current_Client_Id
select new ConventionList // < --- change here!!
{
ID = article.ID,
ARTICLE = article.Article,
REFERENCE = article.Reference,
REMISE = article.Remise,
PRIXVHT = article.PrixVHT,
CLIENT = article.CLIENT,
});
However, getting this to work exactly for your scenario might require some tweaking, as your question is ambiguous about the difference / overlap between the dynamic object, the ConventionList class, and the CommandeList class.
You need to specify your type in the SELECT.
You can't cast anonymous types to declared types
You can't cast unrelated types to each other (command / convention) unless you just slopely pasted the wrong code for us to look at / figure out)
You can't cast List<T> of one type to another type, IEnemurable could work if the generics were related because of covariance.
Updated code with an explicit type in the constructor instead of an anonymous object, again I think you meant Convention but if not change it to the type you need.
var query = (
from article in db.V_CLIENT_PRIX
where article.CLIENT == Current_Client_Id
select new Convention()
{
ID = article.ID,
ARTICLE = article.Article,
REFERENCE = article.Reference,
REMISE = article.Remise,
PRIXVHT = article.PrixVHT,
CLIENT = article.CLIENT,
});
Related
I have the following JSON being sent to an MVC controller:
{
"CId": 374,
"CultureId": 1,
"VGS": null,
"DisplayOrder": 1
}
I am using JSON.Net to convert this to a dynamic object and later assigning the properties into an entity:
public partial class FooEntity
{
public short DisplayOrder { get; set; }
public Nullable<short> VGS { get; set; }
public short CId { get; set; }
public short CultureId { get; set; }
}
Notice that the VGS property we are assigning into is a nullable short, however when trying to create a new instance of the entity and assign the values, I get an error when trying to assign the VGS:
dynamic data = JsonConvert.DeserializeObject(payload);
var foo = new FooEntity();
foo.CId = data.CId;
foo.CultureId = data.CultureId;
foo.VGS = data.VGS; // Errors here
foo.DisplayOrder = data.DisplayOrder;
An exception of type 'System.FormatException' occurred in mscorlib.dll but was not handled in user code
Additional information: Input string was not in a correct format.
As far as I can tell, the json is correct to deserialize into a null value, and since I am assigning into a nullable value, I'm not sure what is causing the error?
JSON.Net does not know what to parse VGS to, which will make it an object. Then you cannot assign an object to VGS. Below is a working example. It can be solved in several ways:
Solution 1: Use explicit cast.
var payload = "{\"CId\": 374, \"CultureId\": 1,\"VGS\": null,\"DisplayOrder\": 1}";
dynamic dyn = JsonConvert.DeserializeObject<FooEntity>(payload);
var foo2 = new FooEntity();
foo.CId = dyn.CId;
foo.CultureId = dyn.CultureId;
foo.VGS = (short?)dyn.VGS; // Note the explicit cast.
foo.DisplayOrder = dyn.DisplayOrder;
Solution 2: Specify type.
var payload = "{\"CId\": 374, \"CultureId\": 1,\"VGS\": null,\"DisplayOrder\": 1}";
dynamic data = JsonConvert.DeserializeObject<FooEntity>(payload); // Specify type.
var foo = new FooEntity();
foo.CId = data.CId;
foo.CultureId = data.CultureId;
foo.VGS = data.VGS;
foo.DisplayOrder = data.DisplayOrder;
But then there's really no reason to use dynamic at all. You can serialize it directly to the entity you want.
FooEntity entity = JsonConvert.DeserializeObject<FooEntity>(payload);
This question already has an answer here:
emit class with a property of the same type as declaring emitted type
(1 answer)
Closed 8 years ago.
I want to generate Types via reflection at runtime that reference each other.
With static code I would do this
public class Order
{
public int Id { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public int Id { get; set; }
public Order Order { get; set; }
}
I can sucessfully generate my Order and my OrderDetails Type with the value type properties.
The code looks like this
var aName = new System.Reflection.AssemblyName("DynamicAssembly");
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
aName, System.Reflection.Emit.AssemblyBuilderAccess.Run);
var mb = ab.DefineDynamicModule(aName.Name);
var tb = mb.DefineType("Order",
System.Reflection.TypeAttributes.Public, typeof(Object));
var pbId = tb.DefineProperty("Id", PropertyAttributes.None, typeof(int), null);
Now I am stuck at this line:
var pbCustomer = tb.DefineProperty("Customer", PropertyAttributes.None, ???, null);
I am required to pass the type of the property to the DefineProperty method but the type does not exist at this point.
Now I could just create a type builder for customer at this point and use tb.CreateType() to get the type but that would not help since Customer needs a reference to Order, too.
Your last paragraph is roughly right, but TypeBuilder derives from Type, so you don't need to call CreateType. That is, create type builders for each of the recursive types, then define the properties passing the respective builders themselves as the return types.
I have two lists with me:
FXCashFlow [contains - amount, paymentdate, TradeId, Currency]
FXTrades [Contains - TradePreferences, TradeId]
What I need to have in the return class is:
Return Object [Type, amount, paymentdate, TradeId, Currency, TradePreference]
Where Type = "Fx", as the data is fetched from Fx class.
For Return Object, I am using a LINQ JOIN like this:
var list = _fxCashflow.GetAll().Join(_fxTrade.GetAll(),
outerKey => outerKey.TradeId,
innerKey => innerKey.TradeId,
(CashFlow, Trade) => new
{
//"Fx", <- This line gives error
CashFlow.TradeId,
Trade.TradeReference,
CashFlow.PaymentAmount,
CashFlow.CurrencyCode,
CashFlow.PaymentDate,
CashFlow.CashflowTypeCode
}
);
I need to insert "Fx", because this data will be concatenated to a class where this "Fx" will identify the records returning from cashflow class.
How can I insert a custom value in this returning object? Or if there's any other way to do this?
Much Appreciated!!
Try to insert it like this instead:
(CashFlow, Trade) => new
{
Type = "Fx",
CashFlow.TradeId,
Trade.TradeReference,
CashFlow.PaymentAmount,
CashFlow.CurrencyCode,
CashFlow.PaymentDate,
CashFlow.CashflowTypeCode
}
Wouldn't it make more sense to introduce an actual Fx class rather than using a string identifier?
public class Fx
{
public int TradeId { get; set; }
public string TradeRef { get; set; }
public decimal PaymentAmount { get; set; }
...
}
(CashFlow, Trade) => new Fx
{
TradeId = CashFlow.TradeId,
TradeRef = Trade.TradeReference,
PaymentAmount = CashFlow.PaymentAmount,
...
}
You can store this information in enum and use it inside your anonymous object or you can define a new property for the anonymous object.
I have a large collection of automatically generated objects. Although they are all of different, non-related classes, all of the objects share some basic properties (name, id, etc.). I do not control the generation of these objects, so unfortunately I cannot take the ideal approach of implementing an interface. I would like to create a method in which I pass an arbitrary one of these objects and do something using these common properties.
The general idea would be something like:
someObj a = new someObj();
a.name = "sara";
diffObj b = new diffObj();
b.name = "joe";
string phrase = string.Format("I am with {0} and {1}",
getName(a), getName(b));
private string getName(object anyObjWithName)
{
return anyObjWithName.name;
}
though naturally this does not work.
I thought a generic method might hold the answer, but the only way I can see to call it with the current type is using genericMethod.Invoke , which still carries the same issue of not being able to resolve the properties of the passed object in the method. This is unlike Calling generic method with a type argument known only at execution time or How to call generic method with a given Type object? where only the type, or properties of the type, are used in the method, as opposed to properties of the object.
I am aware that this would be (very) prone to error, but I can guarantee that all objects encountered will have the common properties being manipulated.
I can guarantee that all objects encountered will have the common properties being manipulated
If that's the case, you can use dynamic:
private string getName(dynamic anyObjWithName)
{
return anyObjWithName.name;
}
Be aware that using any object that does not have a name property will not fail until run-time.
If you want to add a little bit of safety you can catch the RuntimeBinderException that gets thrown if the property does not exist:
private string getName(dynamic anyObjWithName)
{
try {
return anyObjWithName.name;
}
catch(RuntimeBinderException) {
return "{unknown}";
}
}
If you're unhappy with the performance using dynamic as mentioned by D Stanley, you could always try FastMember.
All you need to know to start using it is pretty much shown in the first 2 code examples.
You are creating a Rube Goldberg device there. You should just have all your data objects classes implement a single interface, then you can work on that. Much simpler and less error prone than fiddling with reflection.
The very fact that a lot of objects have common properties but don't share the same ancestry, on in the very least a common interface, shows that something is wrong with your design. Do rethink it.
Multiple ways to accomplish this, simplest probably is to create Interface and declare common methods there, have your object implement it, then change "getName" method take interface object
private string getName(IMyInterface anyObjWithName)
{
return anyObjWithName.name;
}
The correct way to do this is with an interface, if you own the types that you're working with
public interface IEntity
{
int ID { get; set; }
string Name { get; set; }
}
public class TypeOne : IEntity
{
public int ID { get; set; }
public string Name { get; set }
public string BespokePropertyOne { get; set;}
}
public class TypeTwo : IEntity
{
public int ID { get; set; }
public string Name { get; set; }
public float BespokePropertyTwo { get; set; }
}
static void Main(string[] args)
{
List<IEntity> entities = new List<IEntity>();
entities.Add(new TypeOne() { ID = 1, Name = "Bob", BespokePropertyOne = "blablabla" });
entities.Add(new TypeTwo() { ID = 2, Name = "Alice", BespokePropertyTwo = 5.4f });
foreach (IEntity entity in entities)
{
Console.WriteLine("ID: {0} Name: {1}", entity.ID, entity.Name);
}
}
This answer was written before the edit to the question stating that interfaces weren't possible in this case. Perhaps it can help someone else reading this question.
Interface:
interface Iname
{
string Name { get; set; }
}
Use interface:
class A : Iname
{
public string Name { get; set; }
}
class B : Iname
{
public string Name { get; set; }
}
The method:
string GetName(Iname o)
{
return o.Name;
}
Use:
A a = new A { Name = "First" };
B b = new B { Name = "Last" };
Text = GetName(a) + " " + GetName(b);
here is my code:
firstAnswer = p.Answers.Select(z => z.vountcount, z.isSelected).FirstOrDefault()
In the select statement, it returns a syntax error. I am trying to get more then one column.
var firstAnswer = p.Answers.FirstOrDefault().Select(new { VountCount = z.vountcount, IsSelected = z.isSelected });
You must specify a type. Var is the keyword allowing you to instantiate an anonymous type.
You'll either have to create a type or use anonymous types to capture that result:
Anonymous types:
var firstAnswer = p.Answers.Select(z => new { vountcount = z.vountcount, isSelected = z.isSelected }).FirstOrDefault();
The explicit naming is in most cases optional.
Using the var keyword here ensures, that you can assign that anonymous result. If you want to hand that result to some method, it'll get difficult with anonymous types.
Dedicated type:
public class ReducedAnswer
{
public int vountcount { get; set; }
public bool isSelected { get; set; }
public ReducedAnswer()
{
}
}
ReducedAnswer firstAnswer = p.Answers.Select(z => new ReducedAnswer { vountcount = z.vountcount, isSelected = z.isSelected }).FirstOrDefault();
Kept it close to typical LINQ model classes and your naming. Note the use of the type in front of firstAnswer. You could go with var here as well.