Casting objects from jsonb to different objects - c#

I am developing an ASP.NET Core API that uses events with MediatR to publish them in the system. I am looking to include a scheduling service to the Api where events are stored in a database and pull out later and published using MediatR.
The issue I have is that the objects are stored in the database as jsonb and I need to be able to draw them out and cast them to specific object types. I can store the name of the type in the database and access the type that way. However I can't find a solution to this online.
If there is a better way to do this who thing that would be helpful too, but I'm looking for a solution that looks something like this:
var eventType = Type.GetType("foo");
var eventObject = obj.ToObject<eventType>();
If there is a better way of doing this please let me know!
Thanks.

Assuming you could figure out a way to do this, how exactly do you intend to use eventObject after you've managed to create it? Its type is not known at compile time, so you can't write code that uses its methods and properties, because you don't know what methods and properties it has.
For example, if you have a "foo" type with a DoFoo() method and a "bar" type with a DoBar() method, how do you know whether to call DoFoo() or DoBar()?
var eventType = Type.GetType("foo");
var eventObject = obj.ToObject<eventType>();
eventObject.DoFoo(); //How do you know to do this?
eventObject.DoBar(); //How do you know to do this?
The best you can do is a series of if statements:
if (eventType) == typeof(foo))
{
eventObject.DoFoo();
}
if (eventType) == typeof(bar))
{
eventObject.DoBar();
}
Well, if you're going to do that, you may as well cast it in the same if block, which eliminates your problem.
if (obj.GetType() == typeof(foo))
{
((foo)obj).DoFoo();
}
if (obj.GetType() == typeof(bar))
{
((bar)obj).DoBar();
}
If you don't actually need any of its properties or methods, and only need to be able to pass it to some generic method, you can just pass it along as an object. Getting the method is a little tricky though:
mediatR.GetType()
.GetMethod("Publish");
.MakeGenericMethod(eventType);
.Invoke(obj, null);

Related

c# Minimum required of optional parameters

So I'm trying to get a list of relation existing between two table to validate some integration test.
The database is pretty simple : Table1 <- RelationTable -> Table2
I would like to get the existing relation from a list of Table1 Ids or a list of Table2 Ids or both.
If I said that my parameter are all optional, I need to verify that both aren't null or throw a exception if so. If I force both parameter and want to allow one or the other to be null, but not both, I need to create 3 methods to handle it or force the dev who will use the method to add null parameter in the call like the code below which I think it's a ugly way to do it.
Sadly this couldn't be polymorphism because the first params is the same type...
But I would like to allow methodX to just be call method and allow the 3 possible methods into one without allowing method() with no params to be use.
protected async Task<List<Relation>> method1(List<string> table1Ids) => method3(table1Ids, null);
protected async Task<List<Relation>> method2(List<string> table2Ids) => method3(null, table2Ids);
protected async Task<List<Relation>> method3(List<string> table1Ids, List<string> table2Ids)
{
if(table1Ids == null && table2Ids == null)
throw new ArgumentNullException();
// code here
}
To be honest, I could choose if all null throw or 3 method or for bulletproof code choose both and it would work fine, but I'm searching alternate version where I can force a minimum of one parameter but don't said which one is required. I thought maybe attribute from the .Net Framework would do that for me, but I couldn't find something near that. I'm searching for something that could do that out of the box or a custom attribute to do that.
It would be code something like that. Without the if throw because the attribute would validate it.
[MinimumOptionalRequiredAttribute(1)]
protected async Task<List<Relation>> GetRelationFromListOfIds(List<string> table1Ids = null,
List<string> table2Ids = null) {
// code here
}
// Example of code that could be use
{
// Those would work
var byTable1 = GetRelationFromListOfIds(table1Ids);
var byTable2 = GetRelationFromListOfIds(table2Ids:table2Ids);
var byTable1And2 = GetRelationFromListOfIds(table1Ids, table2Ids);
// This would not be allow by the c# intellisense
var throwException = GetRelationFromListOfIds();
}
I know I'm trying to solve everything with one method instead of going with a more "normal" way. I talk about attribute, but it not necessary an attribute. I would expect the code to not compile if you try call methodEmptyParamsNotAllow(). To be honest, I'm not even sure if that is a good idea for code readability. I'm just curious about the idea. Is something similar already exist? Is the idea good? What it would look like?

Add record to DbContext by returning null with a query

I did a research I not found anything so far. Appreciate your help.
As the title says, I'm adding a record to my DbContext by doing a query, and if it returns a null value then I create the record. Otherwise, I modify it.
My question is: Is this a good practice or I shouldn't do this that way? The code is like this:
var desiredEntity = MyDbContext.SingleOrDefault(x => x.Name == "Rob");
if (desiredEntity == null)
{ desiredEntity = new DbSetOfEntity()... //create if doesn't exists }
else
{ desiredEntity.ValueToModify == 3; }
MyDbContext.SaveChanges()
What is the difference between this and creating an entity explicitly and adding it with the DbContext.Add() method?
Edit:
A similar question here is asked, but I don't want to use AddOrUpdate method or Attach and changing the state of the entities manually. I just want to know if my approach is not problematic and what are the differences by using the conventional .Add(myEntity) approach.
AddOrUpdate() is checking record for existance by EntityKey. So if x.Name which you are checking is not Key - your approach is correct.
Also as you have only name value as an input parameter ("Rob") you will have to request record from context, and you will have it attached. So then you can just change it as you need and the changes will be tracked automatically. Alternatively, create it if it doesn't exist and call Add().
Taking into account the above your approach is OK and will work and I dont see any problems with it.
On the other hand, your code should be as simple and elegant as it can be. It is important for supporting your code by you or by your teammates. That is why using constructions like AddOrUpdate or other built-in stuff is good practice. But not a law.
P.S. I am not looking at code like { desiredEntity.ValueToModify == 3; }. This is potentially bad practice as 3 should perhaps be passed to your method as a parameter.

Get the handle of a member of a class that has no instantiation yet

This question is connected (but NOT duplicate) of this one. Consider that I am fairly new to C#.
I would like, if possible, to take the handle of a member of an object that has not been instantiated jet, in order to use it later on. Following previous question, I would like to do something like
List<Action<YourClass>> lst = new List<Action<YourClass>>;
lst.Add(x => x.Member1);
lst.Add(x => x.Member2);
Member1 and Member2 are not supposed to be static member, as their value depend on the state of the object they are member of. Basically I want the handle of their "name", so that I can use it later on when the objects are instantiated. I was thinking about an approach based on string which value is the member name, but maybe there is a better way?
Thanks.
I'm not sure if i understand you right. At first you need to create an instance from your list.
List<Action<YourClass>> lst = new List<Action<YourClass>>;
Else your Add will broke with NullReference-Exception. What you are using in your Add is called anonymus function because the handle isn't saved. If you would like to store this you need a delegate. On this delegate you can call the Invoke-Methode to call it. You are allowed to create your on delegates as well as using predefined like Action.
Here is a small example without any sence, but maybe clarify:
var action = new Action<string>(x => x = x.Substring(1, 1));
//Do some other stuff
action.Invoke("Hallo");
Note that the used var keyword. It detects the result of new Action and take the type of this. In this case it holds Action.
Further note that Action is a predefined delegate. An other would be Func which got one return value. If you need other behaviour you easily can create your own delegates. For this you should read the link.
I found the solution thanks to Henk comment:
Func<myObj, Vector> getVect = new Func<myObj, Vector>
getVect= (myObj => myObj.objVector);
where objVector is NOT a method, but a member of the myObj.
I call getVect in this way:
Vector a= getVect(someObj)

Best way to access attributes

I am working on a framework that uses some Attribute markup. This will be used in an MVC project and will occur roughly every time I view a specific record in a view (eg /Details/5)
I was wondering if there is a better/more efficient way to do this or a good best practices example.
At any rate, I have an a couple of attributes e.g:
[Foo("someValueHere")]
String Name {get;set;}
[Bar("SomeOtherValue"]
String Address {get;set;}
What is the most efficient way/best practice to look for these attributes/Act on their values?
I am currently doing something like this:
[System.AttributeUsage(AttributeTargets.Property)]
class FooAttribute : Attribute
{
public string Target { get; set; }
public FooAttribute(string target)
{
Target = target;
}
}
And in my method where I act on these attributes(simplified example!):
public static void DoSomething(object source)
{
//is it faster if I make this a generic function and get the tpe from T?
Type sourceType = source.GetType();
//get all of the properties marked up with a foo attribute
var fooProperties = sourceType
.GetProperties()
.Where(p => p.GetCustomAttributes(typeof(FooAttribute), true)
.Any())
.ToList();
//go through each fooproperty and try to get the value set
foreach (var prop in fooProperties)
{
object value = prop.GetValue(source, null);
// do something with the value
prop.SetValue(source, my-modified-value, null);
}
}
Attribute.GetCustomAttribute and PropertyInfo/MemberInfo.GetCustomAttribute is the recommended way of getting at attribute objects.
Although, I wouldn't normally enumerate all properties with attributes; you generally want to work a particular attribute so you'd just call GetCustomAttribute directly.If you're looking for attributes on any of your properties, enumerating those properties looking for attributes based on GetCustomAttribute() the way you're doing it, is the best way to do it.
There is not really much choice when dealing with attributes - your code is ok and reasonable as is, it is also unlikley to be your main performance concern. The only immediate thing is to drop ToList call as absolutely unnecessary.
Side notes: performance related question should look approximately
"I've measured my code and portion XXX seems to be taking too much time (YYY) . The time goal for this piece of code is ZZZ. Is my way of doing XXX reasonable/where can I improve it?".
Note that in you case you are missing YYY and ZZZ time portions - so you can't really say if it is slow for your case or not. And you may want to start measurements with DB/other IO bound operations as it more likely to speed up your overall code.
After you figured that this attribute related code is main perfomance issue you can consider some sort of caching of results or even code generation of some sort (either through caching lambdas that would set necessary values or even full blown IL generation).

FindAll in a list of custom objects

Well, I got an object called Mamamia and inside of it has some string properties. I created a list of this object and populated it with 150 items.
I'm trying to use List.FindAll but I reaaally don't know how to do it. I've tried this way:
produto = products.FindAll(delegate(Mamamia cv) {return cv.LocalPackage.Remove(1,21) == cmbPackage.SelectedValue};
I don't know why the delegate is there, I just tried to copy from some other code on the internet.
Thanks in advance!
The delegate is there to see whether the value that you're testing is what you're looking for. The call to Remove looks worryingly like it's mutating the value though - that's rarely a good thing when you're looking through the list. I guess if it's a string then it's not too bad, although it may not be what you're after...
What are the types involved, and what are you looking for? Oh, and are you using C# 3 and/or .NET 3.5? That would make it easier (even C# 3 against .NET 2.0 means you could use a lambda expression instead of an anonymous method).
What's happening when you run the code at the moment? If it's just not finding anything, it may just be because you're testing for reference equality (if SelectedValue returns object).
Try this:
produto = products.FindAll(delegate(Mamamia cv) {
return cv.LocalPackage.Remove(1,21).Equals(cmbPackage.SelectedValue);
});
EDIT:
It sounds like you only want a single value, and if you're using .NET 3.5 it would be more idiomatic to use LINQ in the first place. I would use:
string selectedText = (string) cmbPackage.SelectedValue;
Mamamia item = products.FirstOrDefault
(cv => cv.LocalPackage.Remove(1,21) == selectedText);
if (item != null)
{
// Found it; otherwise item will be null
}

Categories

Resources