'System.ArgumentNullException' in WindsorContainer.Register(). Value cannot be null. Parameter name: name - castle-windsor

I try to make work a code from aspnetboilerplate.
There is a call to WindsorContainer class function
public void Register(Type type, Type impl, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
which looks like this:
iocManager.Register(
typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType),
typeof(EfRepositoryBase<,,>).MakeGenericType(dbContextType, entityType, primaryKeyType),
DependencyLifeStyle.Transient
);
The resuting types are:
[System.RuntimeType] = {Name = "IRepository`2" FullName = "Abp.Domain.Repositories.IRepository`2"}
and
base = {Name = "EfRepositoryBase`3" FullName = null}
We can see that the instantiated by MakeGenericType() concrete type's FullName is null.
The class EfRepositoryBase3 looks like this:
public class EfRepositoryBase<TDbContext, TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
where TDbContext : DbContext
{
... CRUD methods...
}
Why the FullName of it is null and how the issue could be overcome?

FullName can return null in some cases
The fully qualified name of the Type, including the namespace of the
Type but not the assembly; or null if the current instance represents
a generic type parameter, an array type, pointer type, or byref type
based on a type parameter, or a generic type that is not a generic
type definition but contains unresolved type parameters.
You can get a non null name by using the GetGenericTypeDefinition method.

Related

Custom fields in Many2Many JoinTable

I have this model with a custom JoinTable:
type Person struct {
ID int
Name string
Addresses []Address `gorm:"many2many:person_addresses;"`
}
type Address struct {
ID uint
Name string
}
type PersonAddress struct {
PersonID int
AddressID int
Home bool
CreatedAt time.Time
DeletedAt gorm.DeletedAt
}
How is it possible to assign a value to the Home field when creating a new Person?
Method 1
From what I can see in the docs, here's a clean way you might currently do this:
DB.SetupJoinTable(&Person{}, "Addresses", &PersonAddress{})
addr1 := Address{Name: "addr1"}
DB.Create(&addr1)
addr2 := Address{Name: "addr2"}
DB.Create(&addr2)
person := Person{Name: "jinzhu"}
DB.Create(&person)
// Add an association with default values (i.e. Home = false)
DB.Model(&person).Association("Addresses").Append(&addr1)
// Add an association with custom values
DB.Create(&PersonAddress{
PersonID: person.ID,
AddressID: addr2.ID,
Home: true,
})
Here we're using the actual join table model to insert a row with the values we want.
We can also filter queries for the association:
addr := Address{}
// Query association with filters on join table
DB.Where("person_addresses.home = true").
Model(&person).
Association("Addresses").
Find(&addr)
Method 2
Here's a more magical way, by (ab)using the Context to pass values to a BeforeSave hook, in addition to the SetupJoinTable code from above:
func (pa *PersonAddress) BeforeSave(tx *gorm.DB) error {
home, ok := tx.Statement.Context.Value("home").(bool)
if ok {
pa.Home = home
}
return nil
}
// ...
DB.WithContext(context.WithValue(context.Background(), "home", true)).
Model(&person).
Association("Addresses").
Append(&addr2)
This method feels icky to me, but it works.
As you can find this point in the official documents of the GROM, you can implement some methods for each table(struct).
You can implement BeforeCreate() and/or AfterCreate() methods for your join table, gorm will check that method on time!
You can do anything inside those methods to achieve your goal.
here you will find the full documentation.
enjoy ;)

Delphi function generic

I would like to create a generic function. I'm novice in generic.
I've 3 private lists of different type. I want a public generic method for return 1 item of the list.
I've the code below. (I have it simplifie)
TFilter = class
private
FListFilter : TObjectList<TFilterEntity>;
FListFilterDate : TObjectList<TFilterDate>;
FListFilterRensParam : TObjectList<TFilterRensParam>;
public
function yGetFilter<T>(iIndice : integer) : T;
....
function TFilter .yGetFilter<T>(iIndice : integer) : T;
begin
if T = TFilterEntity then
result := T(FListFilter.Items[iIndice])
else
....
end;
I know that code doesn't run, but can you tell me if it's possible to do a thing that it ?
Just introduce a constraint of the generic parameter T. It has to be a class.
From the documentation:
A type parameter may be constrained by zero or one class type. As with interface type constraints, this declaration means that the compiler will require any concrete type passed as an argument to the constrained type param to be assignment compatible with the constraint class.
Compatibility of class types follows the normal rules of OOP type compatibilty - descendent types can be passed where their ancestor types are required.
Change declaration to:
function yGetFilter<T:class>(iIndice : integer) : T;
Update
It appears that in XE5 and earlier you get a compiler error:
E2015 Operator not applicable to this operand type
at this line:
if T = TFilterEntity then
In XE6 and above this bug is fixed.
To circumvent, do as David says in a comment:
if TClass(T) = TFilterEntity then

Select column from non-generic DbSet?

I want to implement a function that accepts a DbSet (non-generic), a string, and object, and returns DbSet. something like the following pseudu:
public static DbSet Any(DbSet set, string propertyName, objectParameter)
{
var tableName = set.TableName;
var columnName = set.GetColumnNameForProperty(propertyName);
var query = string.Format("SELECT TOP(1) {0} FROM {1} WHERE {0} = {2}",
columnName,
tableName,
objectParameter);
}
I think that SQL query is enough since I'll be able to execute it directly on the Database (context.Database.ExecuteSql).
What I want to do is get the table name from the given DbSet, then the column name in the database.
It is not possible from non generic DbSet but this problem can be easily solved by using:
public static IEnumerable<T> Any(DbSet<T> set, string property, objectParameter)
where T : class
{ ... }
Returning DbSet doesn't make sense because once you query data it is not DbSet anymore.
The bigger problem is getting table name from generic DbSet / ObjectSet because this information is not available from those classes. It is almost impossible to get it at all because it requires accessing non public members of items from MetadataWorkspace.

winsdor register a generic type with constructor parameter

i have somthing like this
MyRepository<T> : IRepository<T> {
public MyRepository(string cs){
....
}
so i need to register in winsdor this generic type and give him a parameter
i've been trying to do this like so :
Type t = typeof(IRepository<>);
Type t1 = typeof(Repository<>);
Hashtable props = new Hashtable();
props.Add("cs", "myconnstring");
container.AddComponentWithProperties("key1", t, t1, props);
and i get the following error
Can't create component 'key1' as it has dependencies to be satisfied.
key1 is waiting for the following dependencies:
Keys (components with specific keys)
- cs which was not registered.
Try this:
container.Register(Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(MyRepository<>))
.Parameters(Parameter.ForKey("cs").Eq("myconnstring"));
Check out the fluent registration wiki for more information.
You can use this
var container = new WindsorContainer();
container.Register(Component.For(typeof(ICustomGenericRepository<>))
.ImplementedBy(typeof(CustomGenericRepository<>))
.LifeStyle.Transient);

Generate lambda with Reflection Info

I have Enitity Type, Name of Primary Key and Guid of Primary Id. I want to get element of such Id in LinqToSql.
model.GetTable<T>().Where(t => here equality );
I think I need to generate that Expression myself, but I dont know how :(
http://blog.dynback.com/index.php/2008/11/architecture/database/repository-in-linq-to-sql-getbyid-part/
Result of investigation! Take a look!
I look forward, and after searching through generated by compiler code, in Reflector I found this creation of lambda.
public static T GetById(Guid id)
{
Type entType = typeof(T);
if (!CheckTable(entType)) {
throw new TypeLoadException(string.Format(
"{0} is not Table Entity, has no attribute Table", entType.FullName));
}
string property = GetPrimaryKeyName(entType).Name;
ParameterExpression cs;
var lambda = Expression.Lambda<Func<Personal, bool>>(
Expression.Equal(
Expression.Property(
cs = Expression.Parameter(typeof(T), "p"),
entType.GetProperty(property).GetGetMethod()
),
Expression.Constant(id),
false,
typeof(Guid).GetMethod("Equals")
), new ParameterExpression[] { cs }
);
return Connection.Model.GetTable<T>().Single(lambda);
}
The thing what I need, but I have compiler exception:
Error 5 The type arguments for method
'System.Linq.Enumerable.Single(System.Collections.Generic.IEnumerable,
System.Func)' cannot be
inferred from the usage. Try
specifying the type arguments
explicitly. D:\Projects\Own\Yabeda\Source\trunk\med\Yabeda.Med.Mvc\Data\Oper.cs 48 20 Yabeda.Med.Mvc
Can't find what this Error means!