Using generic classes with ObjectDataSource - asp.net

I have a generic Repository<T> class I want to use with an ObjectDataSource. Repository<T> lives in a separate project called DataAccess. According to this post from the MS newsgroups (relevant part copied below):
Internally, the ObjectDataSource is calling Type.GetType(string) to get the
type, so we need to follow the guideline documented in Type.GetType on how
to get type using generics. You can refer to MSDN Library on Type.GetType:
http://msdn2.microsoft.com/en-us/library/w3f99sx1.aspx
From the document, you will learn that you need to use backtick (`) to
denotes the type name which is using generics.
Also, here we must specify the assembly name in the type name string.
So, for your question, the answer is to use type name like follows:
TypeName="TestObjectDataSourceAssembly.MyDataHandler`1[System.String],TestObjectDataSourceAssembly"
Okay, makes sense. When I try it, however, the page throws an exception:
<asp:ObjectDataSource ID="MyDataSource" TypeName="MyProject.Repository`1[MyProject.MessageCategory],DataAccess" />
[InvalidOperationException: The type specified in the TypeName property of ObjectDataSource 'MyDataSource' could not be found.]
The curious thing is that this only happens when I'm viewing the page. When I open the "Configure Data Source" dialog from the VS2008 designer, it properly shows me the methods on my generic Repository class. Passing the TypeName string to Type.GetType() while debugging also returns a valid type. So what gives?

Do something like this.
Type type = typeof(Repository<MessageCategory);
string assemblyQualifiedName = type.AssemblyQualifiedName;
get the value of assemblyQualifiedName and paste it into the TypeName field. Note that Type.GetType(string), the value passed in must be
The assembly-qualified name of the type to get. See AssemblyQualifiedName. If the type is in the currently executing assembly or in Mscorlib.dll, it is sufficient to supply the type name qualified by its namespace.
So, it may work by passing in that string in your code, because that class is in the currently executing assembly (where you are calling it), where as the ObjectDataSource is not.
Most likely the type you are looking for is
MyProject.Repository`1[MyProject.MessageCategory, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null], DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null

I know this is an old post but I have recently had this problem myself. Another solution would be to replace the inheritance with object composition, e.g.
[DataObject]
public class DataAccessObject {
private Repository<MessageCategory> _repository;
// ctor omitted for clarity
// ...
[DataObjectMethod(DataObjectMethodType.Select)]
public MessageCategory Get(int key) {
return _repository.Get(key);
}
}
This way the ObjectDataSource doesn't know about the repository because its hidden within the class. I have a class library in my facade layer that is a perfectly reasonable place to put this code in the project I am working on.
In addition, if you are using Resharper and interfaces, its possible to get Resharper to do the refactoring using Resharpers "Implement using field" function.

Darren,
Many, many thanks for your post. I've been fighting with this all day. Strangely, in my case, I need to double the square brackets, e.g. for your piece of code:
MyProject.Repository`1[[MyProject.MessageCategory, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null]], DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null
Roger

Related

GetType When Type Is Provided As A String

I understand that C# is a staticly typed language and I already read the answers to this SO posting:
initialize a class by string variable in c#?
My question is a bit different, however. I'm working with a T4 template that provides me with the name of a class as a string parameter. I would give the template code here but what's important is that the type is in a string, so it's the same as having this statement in any C# module:
string s = "MyNamespace.Customer.Model";
Using that string, I need to get the type into a Type variable. Normally, I would use this code when I have access to the actual type:
Type typeModel = typeof(MyNamespace.Customer.Model);
How would I be able to obtain the Type given a string? In other words, my code would ideally look something like this (I know this doesn't work because "s" is a string):
Type typeModel = typeof(s);
(I do know what assembly the type is in, by the way, so I can use that information; also, the assembly containing the Type in question is referenced by the template, for what that's worth...)
Note: I do not want to create an object instance of the Type so please don't suggest a solution that requires using Activator.CreateInstance unless that's the only solution...
Thank you for any ideas you can provide.
The method Type.GetType(string typeName) does what you want, but if you only provide the FullName (namespace and name) of the type, it will only resolve types from the current assembly or mscorlib.
You would need to supply an AssemblyQualifiedName if you want to resolve types outside the current assembly. The problem of course is that multiple assemblies can contain different types with the same name and namespace (thanks Steven Liekens):
string aqn = Assembly.CreateQualifiedName(assemblyName, namespaceAndNameOfType);
Type t = Type.GetType(aqn);
If you don't know the assembly beforehand, you could deal with this by:
Loading all assemblies from the current AppDomain.BaseDirectory, or
Using AppDomain.GetAssemblies() for the currently loaded assemblies
And then iterating over each assembly's GetTypes() method.

Assembly Information

Hi I am working in .net project.
I want to display the assembly information on the page.
User will enter the name of .net assembly in a textbox and then need to display information like all the properties, functions with parameters, constructors, destructor and inherited class names.
Please give some solution for this.
The solution is System.Reflection
using System.Reflection;
For loading assembly dynamically,use
Assembly asm=Assembly.LoadFile(#"Full path of .dll file");
Now to get all types in assembly,use
Type []alltypes=asm.GetTypes();
For information about methods, constructors,parameters,properties use
MethodInfo []GetMethods() ,ConstructorInfo []GetConstructors() ,ParameterInfo []GetParameter() ,PropertyInfo []GetProperty() etc and iterate.
And many more method are there,see the MSDN of System.Reflection

Creating WebControls from fully qualified path (assembly name?)

I have a webpage in ASP.NET 3.5 that will be creating WebControls dynamically. The WebControls that it will be creating will be known by their fully qualified path (ie - System.Web.UI.WebControls.whatever). The reason for this is because I am allowing the user to decide what controls will go on the webpage. Of course, there's more complexity than this, but that is it in a nutshell.
Simply put - how do I create a WebControl on a webpage by it's fully qualified path?
I realize that the answer will probably end up using reflection, but I have little experience using reflection and I don't want to shoot myself in the foot by making a newbie mistake.
try to call this way: Activator.CreateInstance(Type.GetType("TypeName"));
where TypeName is fully qualified name, including assembly. in my case it looked this way:
Activator.CreateInstance(Type.GetType("System.Web.UI.WebControls.Label, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"));
to be sure about full name in your case, try to output typeof(System.Web.UI.WebControls.Label).FullName and use it as a pattern
object widget = Activator.CreateInstance ( Assembly.GetType ( name ) );
where name is the string of the fully qualified type

How do I get the PropertyInfo.PropertyType name of a EntityReference type via reflection

I am writing a small code generator which would read into an edmx file and create business objects on the base of a template. I am using reflection to spit out the type names.
The problem is when I encounter a property (PropertyInfo) of type Entity Reference, (basically an entity property if there is a referential integrity), the PropertyInfo.PropertyType.Name comes as "EntityReference`1" which is not recognized by the compiler.
PropertyInfo.PropertyType.FullName gives "System.Data.Objects.DataClasses.EntityReference`1[[BusinessObjectGenerator.Models.BE_Additional_Info, BusinessObjectGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", which is also not recognized by the C# compiler.
Now I faced the same problem with the Nullable types. And I found the static method Nullable.GetUnderlyingType(type) which solved the issue. How do I get the name of type of a property that is an entity type, a name that the C# compiler recognizes?
Generic types contain ` in their Name. To get the C# readable name of the type, you will need to first check if it is a generic type using Type.IsGenericType. If it is a generic type, then you can use Type.GetGenericArguments() to get the list of type arguments to the generic type. By getting their names, you can put together the generic type name like. For example, if the type is
Dictionary<int, string>
Then, the type name would actually be Dictionary`2. Using GetGenericArguments would return an array with two types (int, and string). From these you can generate the composite name.
Note: Each of the types returned from GetGenericArguments() may itself be a generic type, so you should write this as a recursive algorithm.

Solution explorer of visual studio

In solution explorer of asp.net application we are adding something in References section
for eg:in our project there are sample.Dal,sample.exeption ,system.core etc
What is actually References means,,,can we add by 'using' statement
Using is used for namespace resolution. For example:
using System.Data;
lets you access the DataSet class without typing in the fully qualified name; System.Data.DataSet.
This doesn't however tell the compiler what assembly (DLL) the DataSet class lies in. So you need to tell it. So you refer to System.Data.dll by adding it to the references section in solution explorer.
A reference references assemblies required for the current project.
Where using statements reference namespaces for the current file.
And yes, a referenced namespace must exist in one of the referenced assemblies.
Yes, once you reference another project or assembly, it's namespaces and types are available for use in the project that references them (you must reference the project or assembly before you can use the types within it).
You can either use using declarations or fully-qualified type declarations to access the types, as in:
// Example1: The using keyword.
using System;
void Example1()
{
Int32 myExample;
// etc.
}
// Example2: Fully-qualified type.
void Example2()
{
System.Int32 myExample;
// etc.
}
Note: I have used C# here.

Resources