F# DbContext Inheritance with multiple constructors and property - functional-programming

I'm learning my way to using Ef Core in an F# project.
I'm inheriting the DbContext, and I just want a sense check.
Is this a useful approach in the manner of F#? Using this method of inheritance, and having to explictly set the connectionString property? Would an explict primary constructor been more idiomatic for this?
type TestDbContext =
inherit DbContext
new (conn:string) = {inherit DbContext(); connectionString = Some conn}
new (opts:DbContextOptions<TestDbContext>) = {inherit DbContext(opts); connectionString = None}
val connectionString:Option<string>
member x.ConnectionString
with get() = match x.connectionString with
| Some con -> con
| None -> ""
override __.OnConfiguring (options) =
if not(options.IsConfigured) then
options.UseSqlServer(__.ConnectionString) |>ignore
override __.OnModelCreating modelBuilder = modelBuilder.ApplyConfiguration(TemplateDbBuilder()) |> ignore

Related

Ienumerable of T, T is only available at runtime

I have a method with this signature
public IEnumerable<T> GetAll<T>() where T : new()
{
// Orm Lite Version
return Connection.LoadSelect<T>();
}
At compile time I don't know the Type T. I only know the class name at runtime is it possible to call this method using reflection with something like this?
string TargetTBLName = ...;//TargetTBLName get's it's value at runtime
Type ParentTableClass = Type.GetType(TargetTBLName);
IEnumerable<Type.GetType(TargetTBLName)> test = Repository.GetAll<Type.GetType(TargetTBLName)>();
Any Ideas?
I'd give a Dynamitey library a go. You can do that in many different ways, but I prefer this one because of its simplicity. You can find it here.
var name = InvokeMemberName.Create;
var test = Dynamic.InvokeMember(Repository, name("GetAll", new[]{ParentTableClass }));
foreach(var obj in test)
{
obj.SomeMethodFromMyType();
}
Keep in mind, that if Repository is static, than you have to tweak it a bit to use static invocation context (look up the link).
Now you have a test object, which is a dynamic - you can use it with duck typing (which has some implications on speed, for example), but in general you can do whatever you want to do with a normal IEnumerable<YourType>.
If you want to use reflection:
MethodInfo getAll= typeof(Repository).GetMethod("GetAll");
MethodInfo getAllGeneric= getAll.MakeGenericMethod(ParentTableClass);
object result = getAllGeneric.Invoke(this, null);
//or null, null is Repository is static
var finalObject = result as IEnumerable;
Mind that since this ParentTableClass is an unknown during compilation, you won't have access to anything that the actual type provides - unless you use dynamic approach.

DbContext Generic Method to Find Key Members

Is there a way to find Key Members of an entity (TEntity) when using CodeFirst (DbContext) on a generic context similar to ObjectContext?
I can see how it's done using ObjectContext here.
I'm sorry for the confusion, it seems like even with Code First approach we can find the key members on an entity using the object context as shown below:
var ObjectContext = ((IObjectContextAdapter)DbContext).ObjectContext;
var ObjectSet = ObjectContext .CreateObjectSet<TEntity>();
var EntitySet = ObjectSet.EntitySet;
var KeyMembers = EntitySet.ElementType.KeyMembers;

.NET Compact Framework Reflection call to internal method in .NET framework class

I am trying to load a .NET assembly from a .NET 2.0 CF application. I want to invoke an internal method with three params like so:
var obj = new System.Web.Security.SqlMembershipProvider();
MethodInfo mi = obj.GetType().GetMethod("GenerateSalt",
BindingFlags.NonPublic | BindingFlags.Instance,
null, new Type[] {}, null);
object resObj = mi.Invoke(obj, new object[] {});
When the GetMethod call is executed, a InvalidProgramException is thrown. I can make this call from a regular .NET 2.0 console app test harness, but in .NET 2.0 CF it throws.
What is going on?
You cannot reference the assembly (System.Web.dll) that contains SqlMembershipProvider from a Compact Framework project. As far as I can tell, this type is not available in the Compact Framework.
You are likely getting the exception because you are loading an assembly that contains IL that the Compact Framework Runtime cannot understand.
However, it is fairly simple to re-write what GenerateSalt does yourself, and the compact framework should have everything needed to make it work:
public string GenerateSalt()
{
byte[] data = new byte[0x10];
new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(data);
return System.Convert.ToBase64String(data);
}
No need to use the SqlMembershipProvider (or reflection) at all.
Try using new Type[0] rather than new Type[]

Retrieve private methods of a class using reflection

I want to retrieve the private (implementation and other) methods of a class which implements an interface and also is derived from (inherits) a base class.
How can I achieve this using reflection?
Is there another way to achieve this?
This is what I'm trying to do. I need to view these private methods and their contents. I don't want to invoke them.
Dim assembly As System.Reflection.Assembly
Dim assemblyName As String assemblyName = System.IO.Path.GetFullPath("xyz.dll")
assembly = System.Reflection.Assembly.LoadFile(assemblyName)
assembly.GetType("myClass").Getmethods(Bindings.NonPublic)
assembly.GetType("myClass").GetMethods(BindingFlags.NonPublic) isn't working.
Making the assumption that you're trying to use the private methods of a 3rd party assembly:
I'd urge caution in using private methods, they have been made private for a reason and
might rely on some state that you won't be able to anticipate; Also, if the assembly gets updated in the future, the private behavior may be changed or removed causing you to have to re-write your code to compensate.
However, there are two methods at your disposal, if you want to continue.
One way us using the new Dynamic keyword in .net 4:
http://igoro.com/archive/use-c-dynamic-typing-to-conveniently-access-internals-of-an-object/
To use reflection, this question may help you:
How do I use reflection to invoke a private method?
Hope this helps.
BindingFlags
You must specify Instance or Static along with Public or NonPublic or no members will be returned.
Assembly myAssembly;
myAssembly = Assembly.LoadFrom(#"c:\xyz.dll");
Type myType = myAssembly.GetTypes()[0]; //change 0 according to your class type.
BindingFlags eFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
MethodInfo myMethod = myType.GetMethod("Methodname", eFlags);
object obj1 = myAssembly.CreateInstance(myType.FullName);
object obj2 = myMethod.Invoke(obj1, new object[2] { parameters1, parameters1 });

C# CF2.0 - System.Activator and Internal classes

I've got a data provider that contains a collection of entities. I only want to be able to create a new entity through the data provider.
I.e, to create a new record I need to use:
Entity entity = Provider.AddNew();
enity.set_Properties... etc
My issue is that if I set my entities to Internal, System.Activator cannot create an Instance of them. Each of my Data Providers uses a Base class with the generic type of the entity passed through.
So at the moment my AddNew() method contains the following:
public T AddNew()
{
T added = Activator.CreateInstance<T>();
this.Collection.Add(added);
return added;
}
It's obviously not the end of the world if I can instantiate a new entity manually outside of the Data Provider namespaces, but it seems pointless considering there's no way to ever save them, so why give the option to do so?
EDIT: Forgot to mention that all my providers, entities, etc are in the same namespace.
Don't use the Activator, which relies on a public constructor. Instead use reflection to find the parameterless constructor and then call it. Something along these lines:
Type t = typeof(MyType);
var parameterlessCtor = (from c in t.GetConstructors(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
where c.GetParameters().Length == 0
select c).FirstOrDefault;
if(parameterlessCtor != null) instance = parameterlessCtor.Invoke(null);

Resources