Many sharepoint classes are not available to inherit from because the default contructor is hidden. The following (quick and untested!) code uses the CodeDom to generate a wrapper class.
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Reflection;
using Microsoft.SharePoint;
namespace DevHoleDemo.ClassWrapper
{ class Program
{ static void Main(string[] args)
{ ClassWrapper w = new ClassWrapper("DevHoleDemo", "SPWebWrapper", typeof(SPWeb)); string s = w.GetCode();
}
}
public class ClassWrapper
{ string m_namespace;
string m_className;
SortedDictionary<string, int> m_imports;
SortedDictionary<string, int> m_modules;
StringBuilder m_sb;
Type m_t;
public ClassWrapper(string targetNamespace, string targetClassName, object source)
: this(targetNamespace, targetClassName, source.GetType())
{ }
public ClassWrapper(string targetNamespace, string targetClassName, Type t)
{ m_namespace = targetNamespace;
m_className = targetClassName;
m_t = t;
m_imports = new SortedDictionary<string, int>();
m_modules = new SortedDictionary<string, int>();
}
public string GetCode()
{ return GetCode("CS"); }
public string GetCode(string language)
{ Generate(language);
string results = m_sb.ToString();
results = results.Replace("void implicit_operator_", "implicit operator "); return results;
}
protected void AddNamespace(Type t)
{ if (m_imports.ContainsKey(t.Namespace))
m_imports[t.Namespace]++;
else
m_imports.Add(t.Namespace, 1);
if (m_modules.ContainsKey(t.Module.Name))
m_modules[t.Module.Name]++;
else
m_modules.Add(t.Module.Name, 1);
}
protected CodeTypeReference GetCodeTypeReference(Type t)
{ AddNamespace(t);
if (t.IsByRef)
return new CodeTypeReference(t.Name.TrimEnd('&')); else
return new CodeTypeReference(t);
}
protected void Generate(string language)
{
m_sb = new StringBuilder();
TextWriter tw = new StringWriter(m_sb);
CodeDomProvider cdp = CodeDomProvider.CreateProvider(language);
CodeTypeReferenceExpression tre = new CodeTypeReferenceExpression(m_t);
//namespace
CodeNamespace ns = new CodeNamespace(m_namespace);
//class
CodeTypeDeclaration class1 = new CodeTypeDeclaration(m_className);
ns.Types.Add(class1);
class1.IsClass = true;
//base object field
CodeMemberField cmf1 = new CodeMemberField(GetCodeTypeReference(m_t), "m_" + m_t.Name);
class1.Members.Add(cmf1);
//constructor
CodeConstructor cc = new CodeConstructor();
cc.Attributes = MemberAttributes.Public;
CodeParameterDeclarationExpression cpde1 = new CodeParameterDeclarationExpression(GetCodeTypeReference(m_t), m_t.Name);
cc.Parameters.Add(cpde1);
CodeFieldReferenceExpression cfre1 = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "m_" + m_t.Name);
cc.Statements.Add(new CodeAssignStatement(cfre1, new CodeArgumentReferenceExpression(m_t.Name)));
class1.Members.Add(cc);
//methods
foreach (MethodInfo mi in m_t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy))
{ if (!mi.IsSpecialName)
{ CodeMemberMethod meth = new CodeMemberMethod();
meth.Attributes &= ~MemberAttributes.AccessMask & ~MemberAttributes.ScopeMask;
meth.Attributes |= MemberAttributes.Public;
if ((mi.Attributes & MethodAttributes.Static) == MethodAttributes.Static)
meth.Attributes |= MemberAttributes.Static;
if ((mi.Attributes & MethodAttributes.Virtual) != MethodAttributes.Virtual)
meth.Attributes |= MemberAttributes.Final;
meth.Name = mi.Name;
List<CodeExpression> prms = new List<CodeExpression>();
foreach (ParameterInfo ri in mi.GetParameters())
{ CodeParameterDeclarationExpression cpde2 = new CodeParameterDeclarationExpression(GetCodeTypeReference(ri.ParameterType), ri.Name);
CodeArgumentReferenceExpression care1 = new CodeArgumentReferenceExpression(ri.Name);
CodeDirectionExpression cde = null;
if (ri.IsOut)
{ cpde2.Direction = FieldDirection.Out;
cde = new CodeDirectionExpression(FieldDirection.Out, care1);
}
meth.Parameters.Add(cpde2);
if (cde == null)
prms.Add(care1);
else
prms.Add(cde);
}
CodeMethodReferenceExpression cmre1;
if ((mi.Attributes & MethodAttributes.Static) == MethodAttributes.Static)
cmre1 = new CodeMethodReferenceExpression(tre, mi.Name);
else
cmre1 = new CodeMethodReferenceExpression(cfre1, mi.Name);
if (mi.ReturnType == typeof(void))
{ meth.Statements.Add(new CodeMethodInvokeExpression(cmre1, prms.ToArray()));
}
else
{ meth.Statements.Add(new CodeMethodReturnStatement(new CodeMethodInvokeExpression(cmre1, prms.ToArray())));
}
meth.ReturnType = GetCodeTypeReference(mi.ReturnType);
class1.Members.Add(meth);
}
}
//properties
foreach (PropertyInfo pi in m_t.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy))
{ CodeMemberProperty prop = new CodeMemberProperty();
prop.Name = pi.Name;
prop.Attributes &= ~MemberAttributes.AccessMask & ~MemberAttributes.ScopeMask;
prop.Attributes |= MemberAttributes.Public | MemberAttributes.Final;
List<CodeExpression> indices = new List<CodeExpression>();
if (pi.GetIndexParameters().Length > 0)
{ foreach (ParameterInfo pii in pi.GetIndexParameters())
{ CodeParameterDeclarationExpression cpde3 = new CodeParameterDeclarationExpression(GetCodeTypeReference(pii.ParameterType), pii.Name);
prop.Parameters.Add(cpde3);
CodeArgumentReferenceExpression care3 = new CodeArgumentReferenceExpression(pii.Name);
indices.Add(care3);
}
}
prop.Type = GetCodeTypeReference(pi.PropertyType);
prop.HasGet = pi.GetGetMethod() != null;
if (prop.HasGet)
{ if (pi.GetIndexParameters().Length > 0)
prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeArrayIndexerExpression(cfre1, indices.ToArray())));
else
prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(cfre1, pi.Name)));
}
prop.HasSet = pi.GetSetMethod() != null;
if (prop.HasSet)
{ if (pi.GetIndexParameters().Length > 0)
prop.SetStatements.Add(new CodeAssignStatement(new CodeArrayIndexerExpression(cfre1, indices.ToArray()), new CodePropertySetValueReferenceExpression()));
else
prop.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(cfre1, pi.Name), new CodePropertySetValueReferenceExpression()));
}
class1.Members.Add(prop);
}
//implicit casts
CodeMemberMethod castFrom = new CodeMemberMethod();
castFrom.Name = "implicit_operator_" + m_t.Name;
castFrom.Attributes &= ~MemberAttributes.AccessMask & ~MemberAttributes.ScopeMask;
castFrom.Attributes |= MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static;
CodeParameterDeclarationExpression cpde4 = new CodeParameterDeclarationExpression(new CodeTypeReference(m_className), m_className);
castFrom.Parameters.Add(cpde4);
CodeArgumentReferenceExpression care4 = new CodeArgumentReferenceExpression(m_className);
CodeFieldReferenceExpression cfre3 = new CodeFieldReferenceExpression(care4, "m_" + m_t.Name);
castFrom.Statements.Add(new CodeMethodReturnStatement(cfre3));
castFrom.ReturnType = new CodeTypeReference(typeof(void));
class1.Members.Add(castFrom);
CodeMemberMethod castTo = new CodeMemberMethod();
castTo.Name = "implicit_operator_" + m_className;
castTo.Attributes &= ~MemberAttributes.AccessMask & ~MemberAttributes.ScopeMask;
castTo.Attributes |= MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static;
CodeParameterDeclarationExpression cpde5 = new CodeParameterDeclarationExpression(new CodeTypeReference(m_t), m_t.Name);
castTo.Parameters.Add(cpde5);
CodeArgumentReferenceExpression care5 = new CodeArgumentReferenceExpression(m_t.Name);
CodeObjectCreateExpression coce = new CodeObjectCreateExpression(new CodeTypeReference(m_className), care5);
castTo.Statements.Add(new CodeMethodReturnStatement(coce));
castTo.ReturnType = new CodeTypeReference(typeof(void));
class1.Members.Add(castTo);
//write imports
foreach (KeyValuePair<string, int> kvp in m_imports)
{ ns.Imports.Add(new CodeNamespaceImport(kvp.Key));
}
//write modules comments
ns.Comments.Add(new CodeCommentStatement("References to the following modules must be added:")); foreach (KeyValuePair<string, int> kvp in m_modules)
{ ns.Comments.Add(new CodeCommentStatement(string.Format("\t {0}", kvp.Key))); }
cdp.GenerateCodeFromNamespace(ns, tw, null);
tw.Close();
}
}
}