Here is how I get data from database and update using lambda expression .
item _myItem = db.myDBContext.items.Where(x => x.id == 0).SingleOrDefault();
_myItem.field1 = "myValueForField1";
_myItem.field2 = "myValueForField2";
_myItem.field3 = "myValueForField3";
_myItem.field4 = "myValueForField4";
db.myDBContext.SubmitChanges();
It's just a sample, my table has many columns.
If I follow this way, I have to assign each column (field1,field2,..).
If I have 20 columns, I have to write 20 lines of code.
Can I assign field name dynamically ?
Like
_myItem[dynamicFieldName] = ...;
Or is there any way to make it better ?
I just want to assign the field names dynamically.
Without using reflection, you cannot assign fields dynamically in that way.
Using reflection, you can, but there is a performance hit associated.
for example:
var myField = "field1";
var field = _item.GetType().GetField(myField); // perhaps GetProperty() - depending on if its a field or a property.
field.SetValue(_item,"myValueForField1");
Obviously that can be done in a loop, with all your field names in an array or list of some sort.
Try this one:
item _myItem = db.myDBContext.items.Where(x => x.id == 0).SingleOrDefault();
var typ = typeof(item);
typ.GetProperties().ToList().Foreach(m=> m.SetValue(_myItem,"yourvalue", null));
db.myDBContext.SubmitChanges();
You can use reflection:
PropertyInfo pInfo = _myItem.GetType().GetProperty("field2"):
pInfo.SetValue(_myItem, "myValueForField2");
You can not use reflection.
You would make indexer in your Item class. And use extension methods to convert to specific type.
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
static class MyExtensions
{
public static int toInt32(this string field)
{
return Convert.ToInt32(field);
}
}
class MySpecificList
{
Dictionary<string, string> _fields = new Dictionary<string, string>();
public string this[string name]
{
get
{
return _fields[name];
}
set
{
_fields[name] = value;
}
}
static void Main(string[] args)
{
MySpecificList list = new MySpecificList();
list["field1"] = "1";
Console.WriteLine(list["field1"].toInt32() + 1);
}
}
}
Related
I have table called Asset. It has lot of columns. I only want to select two of them and use them separately.
Both of these columns are strings.
Linq query :
public static List<string> GetAssetIdsWithNames()
{
using (var db = DbManager.Get())
{
var result = db.Assets.SelectMany(i=> new[] { i.AssetName, i.AssetId }).Distinct().ToList();
return result;
}
}
Where I want to use them :
var assetList = AssetManager.GetAssetIdsWithNames();
//CURRENCYBOX IS A DROPDOWN
CurrencyBox.DataSource = assetList;
CurrencyBox.DataBind();
foreach (var item in assetList)
{
CurrencyBox.DataValueField = //asset id goes here
CurrencyBox.DataTextField =//asset name goes here
break;
}
You cannot access the anonymous type outside of the local scope.
Anonymous types can only be returned as Object outside their local scope and their properties inspected via reflection.
So in this scenario, you are likely better off to use a typed data contract and map from your Asset entity instead and then access it from your calling method.
Your use of SelectMany seems odd too, you probably are after Select instead.
public class AssetDto
{
public string Name { get;set; }
public string Id { get; set; }
}
public static List<AssetDto> GetAssetIdsWithNames()
{
using (var db = DbManager.Get())
{
var result = db.Assets.Select(i=> new AssetDto { Name = i.AssetName, Id = i.AssetId }).ToList();
return result;
}
}
You could use named value tuples for that so you don't need to create an extra class
public static List<(string Name, int Id)> GetAssetWithIds()
{
using (var db = DbManager.Get())
{
var result = db.Assets
.Select(a => new { a.AssetName, a.AssetId })
.Distinct().AsEnumerable()
.Select(a => (a.AssetName, a.AssetId))
.ToList();
return result;
}
}
You will need to add System.ValueTuple
I'm trying to set property values straight from database so i could initiate new object
Object AllValues = new Object(); and access it in code like this AllValues.MediumRunTime;
using Entity Framework and it's returning 0's which it should't.
Also ReSharper is throwing Field value is never assigned warning
My table is Values{name, value, units} and contains around ~100 records.
This is my AllValues class
using System.Linq;
namespace RunTimes
{
public class AllValues
{
private long value;
public long ShortRunTime
{
get => value;
set
{
using (var data = new ModelData())
{
var prop = data.Values.FirstOrDefault(c => c.name == "ShortRunTime");
value = prop.value;
}
}
}
public long MediumRunTime
{
get => value;
set
{
using (var data = new ModelData())
{
var prop = data.Values.FirstOrDefault(c => c.name == "MediumRunTime");
value = prop.value;
}
}
}
...
And im trying to access it on Program.cs like this
AllValues av = new AllValues();
Console.WriteLine($"Medium run time: {av.MediumRunTime}");
A property setter is not the place to 'set a field with the value from the database', you use it to set the value of the property after you first loaded it from the database.
So instead of your AllValues class as it currently stands, you would have a class with some simple properties, such as:
class AllValues
{
public string ShortRunTime { get; set; }
public string MediumRunTime { get; set; }
// ...
}
and then instantiate it like this:
var av = new AllValues();
using (var data = new ModelData())
{
av.ShortRunTime = data.Values.FirstOrDefault(c => c.name == "ShortRunTime")?.Value;
av.MediumRunTime = data.Values.FirstOrDefault(c => c.name == "MediumRunTime")?.Value;
// ...
}
After this you can work with your class in memory. The 'trick' is to separate concerns: your 'transformed class' (AllValues) and loading data from the database are 2 different concerns that should be treated separately.
Assume A through Z to be 26 classes I defined. In the following example:
private List<A> _listA;
private List<B> _listB;
// private List<C>, and so on, through...
private List<Z> _listZ;
private void setLabelA()
{
LabelA.Text = _listA.Count;
}
// private void setLabelB() exists
// and so does setLabelC()
// and so on, all the way through to...
private void setLabelZ()
{
LabelA.Text = _listZ.Count;
}
It seems to me that there is no way to shorten this other than the following:
private void setLabel<genericType>(List<genericType> list)
{
if(list is List<A>) LabelA.Text = _listA.Count;
else if(list is List<B>) LabelB.Text = _listB.Count;
else if(list is List<C>) LabelC.Text = _listC.Count;
// and so on...
else if(list is List<Z>) LabelZ.Text = _listZ.Count;
}
Overloading the function name doesn't reduce the number of lines of code:
private void setLabel(List<A> list)
{
LabelA.Text = _listA.Count;
}
private void setLabel(List<B> list)
{
LabelB.Text = _listB.Count;
}
I prefer to use the is operator to determine which Label to set, because it preserves space (in this scenario, 50 lines of meaningless brackets and 25 lines of slightly-different function names). However, a Stack Overflow user recommended that I not use generics, and instead use separate functions, one for each Label. Although this solution will work, I prefer to not do so.
Is there any benefit towards NOT using the is operator, and towards explicitly typing my functions?
The benefit is that your type checking is static, rather than dynamic. If someone passes in a List<SomeRandomeClassYouDontSupport> to the first method, then the code will compile and just not work properly at runtime. It'll either do nothing, throw an exception, or whatever you code it to do, but the point is that the caller won't be able to see that they did something wrong until they run the code.
When you have multiple overloads then the validation is done at compile time. If an unsupported type is provided then the code won't even compile rather than compiling and not working.
It's also an important semantic difference. Generics are there to say, "This method will work regardless of what the type is". When creating a list there are no right and wrong type arguments to provide. You can create a list of any type that you want. That's an appropriate use of generics, because lists are a conceptually generic data structure. Having several overloads is a way of saying, "This finite list of types is supported." You're in the latter case, so that makes that behavior clearer to the caller, so they'll understand what the method needs to do just by looking at its signature.
Having said all of that, it looks like this isn't even a situation where you should be doing either. If you really wanted to have a method accepting one of a finite number of types known at compile time as a parameter, overloads are the right way to do it, but in your case, you shouldn't be doing any of this at all. You should be binding these UI compontents to a view as mentioned in this comment.
Why not just make your own classes which derive their own fields automatically?
private class ListWithText : List<T>
{
int Text {
get { return this.Count; }
}
}
ListWithText<A> LabelA = new ListWithText<A>();
Console.WriteLine(LabelA.Text);
I will NOT comment about whether it is a good practice or not to do what you are doing :).
If the absence of a label for a given list is NOT the end of the world for you and if you rely on some naming conventions for your label fields so that all labels are named for example "LabelX" where X is your type that will be used for generic lists, you can do that:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Labels
{
class Program
{
static void Main(string[] args)
{
Container c = new Container();
c.ApplyLabels();
}
}
public class A
{
}
public class B
{
}
public class C
{
}
public class Container
{
private Label LabelA = new Label ();
private Label LabelB = new Label ();
private Label LabelC = new Label ();
private List<A> _listA = new List<A> ();
private List<B> _listB = new List<B> ();
private List<C> _listC = new List<C> ();
public void ApplyLabels ()
{
var allFields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Dictionary<Type, FieldInfo> listFields = new Dictionary<Type, FieldInfo>();
Dictionary<Type, FieldInfo> labelMappings = new Dictionary<Type, FieldInfo>();
Dictionary<string, Type> namespacesForListGenericTypes = new Dictionary<string, Type>();
List<FieldInfo> possibleLabelFields = new List<FieldInfo>();
foreach (var field in allFields)
{
if (field.FieldType.IsGenericType)
{
var genericTypeDef = field.FieldType.GetGenericTypeDefinition();
if (genericTypeDef == typeof (List<>))
{
var genericArgument = field.FieldType.GetGenericArguments()[0];
listFields.Add(genericArgument, field); // remember list fields and for each list what generic type it has!
namespacesForListGenericTypes[genericArgument.Name] = genericArgument;
}
}
else if (typeof (Label).IsAssignableFrom (field.FieldType))
{
possibleLabelFields.Add(field);
}
}
foreach (var possible in possibleLabelFields)
{
if (possible.Name.Length < 6) continue;
var typeName = possible.Name.Substring(5);
Type genericListType;
if (namespacesForListGenericTypes.TryGetValue (typeName, out genericListType))
{
labelMappings[genericListType] = possible;
}
}
foreach (var list in listFields)
{
FieldInfo destination;
if (false == labelMappings.TryGetValue (list.Key, out destination))
{
continue;
}
var destinationLabel = destination.GetValue(this) as Label;
if (destinationLabel == null) continue;
var listValue = list.Value.GetValue(this) as IList;
var cnt = listValue == null ? 0 : listValue.Count;
destinationLabel.Text = cnt.ToString();
}
}
}
public class Label
{
public string Text { get; set; }
}
}
Basically, I want to know if I can do this with two ObservableCollections:
oldList = newList;
I have two lists that get populated throughtout my app, and each time they get populated, I want the 'new' values to become the 'old' values, and then get a new set of values to put in the 'new' list.
is it that easy? Any other way to do this without iterating over the whole newList every time?
EDIT: This is how the new list is being populated. Basically, I just want the contents of the newList to be put into the oldList.
foreach (object obj in ts.GetVariables())
{
if ((obj.ToString() != "_SMSTSReserved2") || (obj.ToString() != "OSDJoinPassword") || (obj.ToString() != "OSDLocalAdminPassword"))
{
TSVar var = new TSVar();
var.TSVarName = obj.ToString();
var.TSVarValue = ts[obj.ToString()];
newList.Add(var);
}
}
oldList.Clear();
foreach (TSVar var in newList)
{
oldList.Add(var);
}
If you use the extension method listed below, what you are trying to do becomes a one liner:
oldList.Replace(newList);
I would create an Extension Method for ObservableCollection like this:
public static class ObservableCollectionExtensionMethods
{
public static void Replace<T>(this ObservableCollection<T> old, ObservableCollection<T> #new)
{
old.Clear();
foreach (var item in #new)
{
old.Add(item);
}
}
}
And this is how you would use it:
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ExtensionMethods
{
[TestClass]
public class ObservableCollectionExtensionMethodsTest
{
[TestMethod]
public void ReplaceTest()
{
// Arrange
var old = new ObservableCollection<string> { "1"};
var #new = new ObservableCollection<string> {"2"};
// Act
old.Replace(#new);
// Assert
Assert.AreEqual("2", old.First());
}
}
}
I think this is what you may be looking for? This will add everything that was in newList to your oldList.
ObservableCollection<YourType> oldList = new ObservableCollection<YourType>(newList);
newList.clear();
//put new stuff in your list here.
I have two lists of strings. One is object friendly name and other one is object class name.
"Car","Animal","Plane"
"MachineClass","AnimalClass","FlyClass".
I use friendly names to show user input and class names to dynamically create class instances by using reflection, so i need both lists and like you can see "Car" as friendly name can be bound to "Machine.cs".
I need some more creative way of working and translating both of these lists rather than using switch statement which converts from one string to other, those lists have numerous items and i can make small spelling which will cause error. Moreover sometimes, i send string of test name for evaluation whereas same problem with spellings can apply there.
I tried to think about using enums but still digits doesn't ring a bell for conversions between both lists.
public enum Things
{
Car,
Animal,
Plane
}
var dict = new Dictionary<Things, string> {
{ Things.Car, "MachineClass" },
{ Things.Animal, "AnimalClass" },
{ Things.Plane, "FlyClass" } };
string classname = dict[Things.Plane]; // FlyClass
Now if you wanted real types, that you can instantiate:
var realtypes = dict.ToDictionary(
kvp => kvp.Key,
kvp => System.Type.GetType("Namespace." + kvp.Value));
A fully working example is on http://ideone.com/TTuBP:
using System;
using System.Collections.Generic;
using System.Linq;
//public interface IThing {}
public class MachineClass /* : IThing */ { }
public class AnimalClass /* : IThing */ { }
public class Plane /* : IThing */ { }
public class Program
{
public enum Things
{
Car,
Animal,
Plane
}
private static readonly IDictionary<Things, string> _classNameMap =
new Dictionary<Things, string> {
{ Things.Car, "MachineClass" },
{ Things.Animal, "AnimalClass" },
{ Things.Plane, "FlyClass" } };
public static void Main(string[] args)
{
var realtypes = _classNameMap.ToDictionary(
kvp => kvp.Key,
kvp => System.Type.GetType(/*"Namespace." +*/ kvp.Value));
Type dynamicType = realtypes[Things.Plane]; // typeof(Namespace.FlyClass)
foreach (var realtype in realtypes)
Console.WriteLine("{0}, class {1}",
realtype.Key, realtype.Value);
}
}
Why not use a dictionary?
Dictionary<string, string> classMap_ = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
classMap_["Car"] = "MachineClass";
classMap_["Animal"] = "AnimalClass";
classMap_["Plane"] = "FlyClass":
Creating the appropriate class is as simple as:
string className = classMap_["Car"];
Use maps HashMap to maintain friendly name and class name mapping
I don't recomend to use reflection for creation objects of classes from performance point of view, insteed you can use lambda expressions to create objects
look at the following code
var animals = new Dictionary<string, Func<object>>
{
{"Animal 1", () => new MyAnimal1()},
{"Animal 2", () => new MyAnimal2()}
};
var createAnimal = animals["Animal 1"];
var animal = createAnimal();
where
private class MyAnimal1
{
}
private class MyAnimal2
{
}
insteed this classes you should use your classes.
Why not using databinding?
class Wrapper
{
public string UserFriendly{get;set;}
public string Technical{get;set;}
}
var data = new[]
{
new Wrapper("Car", "MachineClass"),
new Wrapper("Plane", "FlyClass"),
};
combo.Datasource = data;
combo.DisplayMember = "UserFriendly";
combo.ValueMember = "Technical";
Combo will display the friendlyname but when asking for SelectedValue you will get the technical name.