public override CodeExpression GetCodeExpression (BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
if (entry == null)
throw new NullReferenceException (".NET emulation (entry == null)");
var ret = new CodeMethodInvokeExpression ();
ret.Method = new CodeMethodReferenceExpression (new CodeTypeReferenceExpression (typeof (RouteValueExpressionBuilder)), "GetRouteValue");
var thisref = new CodeThisReferenceExpression ();
CodeExpressionCollection parameters = ret.Parameters;
parameters.Add (new CodePropertyReferenceExpression (thisref, "Page"));
parameters.Add (new CodePrimitiveExpression (entry.Expression));
parameters.Add (new CodeTypeOfExpression (new CodeTypeReference (entry.DeclaringType)));
parameters.Add (new CodePrimitiveExpression (entry.Name));
return ret;
}
private void CreateConstructorBody(GMethod constructor, CodeConstructor con, string uName)
{
if (!type.IsRootType)
{
con.BaseConstructorArgs.Add(
new CodeCastExpression(TypeReference("net.sf.jni4net.inj.INJEnv"), new CodePrimitiveExpression(null)));
con.BaseConstructorArgs.Add(new CodePrimitiveExpression(0));
}
var parameters = new CodeExpression[constructor.Parameters.Count + 1];
for (int p = 0; p < constructor.Parameters.Count; p++)
{
parameters[p + 1] = new CodeVariableReferenceExpression(constructor.ParameterNames[p]);
}
parameters[0] = new CodeThisReferenceExpression();
con.Statements.Add(
new CodeMethodInvokeExpression(CurrentTypeEx, uName, parameters));
}
static CodeMemberProperty GetIndexer()
{
var indexer = new CodeMemberProperty();
indexer.Attributes = MemberAttributes.Public | MemberAttributes.Final;
indexer.Name = "Item";
indexer.Type = new CodeTypeReference(typeof(object));
indexer.HasSet = true;
indexer.HasGet = true;
indexer.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "field"));
//return RecordHelper.Get(this, field);
//RecordHelper.Set(this, field, value);
var helper = new CodeTypeReferenceExpression("RecordHelper");
var field = new CodeVariableReferenceExpression("field");
var _this = new CodeThisReferenceExpression();
var value = new CodeVariableReferenceExpression("value");
var g = new CodeMethodInvokeExpression(helper, "Get", _this, field);
indexer.GetStatements.Add(new CodeMethodReturnStatement(g));
var s = new CodeMethodInvokeExpression(helper, "Set", _this, field, value);
indexer.SetStatements.Add(s);
return indexer;
}
/// <summary>
/// Generates the code to store the views in a C# or a VB file based on the
/// options passed in by the user.
/// </summary>
/// <param name="mappingCollection"></param>
/// <param name="generatedViews"></param>
/// <param name="sourceWriter"></param>
/// <param name="provider"></param>
/// <returns></returns>
private static void GenerateAndStoreViews(StorageMappingItemCollection mappingCollection,
Dictionary<EntitySetBase, string> generatedViews, TextWriter sourceWriter, CodeDomProvider provider, IList<EdmSchemaError> schemaErrors)
{
EdmItemCollection edmCollection = mappingCollection.EdmItemCollection;
StoreItemCollection storeCollection = mappingCollection.StoreItemCollection;
//Create an emtpty compile unit and build up the generated code
CodeCompileUnit compileUnit = new CodeCompileUnit();
//Add the namespace for generated code
CodeNamespace codeNamespace = new CodeNamespace(EntityViewGenerationConstants.NamespaceName);
//Add copyright notice to the namespace comment.
compileUnit.Namespaces.Add(codeNamespace);
foreach (var storageEntityContainerMapping in mappingCollection.GetItems<StorageEntityContainerMapping>())
{
//Throw warning when containerMapping contains query view for bug 547285.
if (HasQueryView(storageEntityContainerMapping))
{
schemaErrors.Add(new EdmSchemaError(
Strings.UnsupportedQueryViewInEntityContainerMapping(storageEntityContainerMapping.Identity),
(int)StorageMappingErrorCode.UnsupportedQueryViewInEntityContainerMapping,
EdmSchemaErrorSeverity.Warning));
continue;
}
#region Class Declaration
string edmContainerName = storageEntityContainerMapping.EdmEntityContainer.Name;
string storeContainerName = storageEntityContainerMapping.StorageEntityContainer.Name;
string hashOverMappingClosure = MetadataMappingHasherVisitor.GetMappingClosureHash(edmCollection.EdmVersion, storageEntityContainerMapping);
StringBuilder inputForTypeNameContent = new StringBuilder(hashOverMappingClosure);
string viewStorageTypeName = EntityViewGenerationConstants.ViewGenerationTypeNamePrefix + StringHashBuilder.ComputeHash(MetadataHelper.CreateMetadataHashAlgorithm(edmCollection.EdmVersion), inputForTypeNameContent.ToString()).ToUpperInvariant();
//Add typeof expression to get the type that contains ViewGen type. This will help us in avoiding to go through
//all the types in the assembly. I have also verified that this works with VB with a root namespace prepended to the
//namespace since VB is picking up the type correctly as long as it is in the same assembly even with out the root namespace.
CodeTypeOfExpression viewGenTypeOfExpression = new CodeTypeOfExpression(EntityViewGenerationConstants.NamespaceName + "." + viewStorageTypeName);
//Add the assembly attribute that marks the assembly as the one that contains the generated views
CodeAttributeDeclaration viewGenAttribute = new CodeAttributeDeclaration(EntityViewGenerationConstants.ViewGenerationCustomAttributeName);
CodeAttributeArgument viewGenTypeArgument = new CodeAttributeArgument(viewGenTypeOfExpression);
viewGenAttribute.Arguments.Add(viewGenTypeArgument);
compileUnit.AssemblyCustomAttributes.Add(viewGenAttribute);
//Add the type which will be the class that contains all the views in this assembly
CodeTypeDeclaration viewStoringType = CreateTypeForStoringViews(viewStorageTypeName);
//Add the constructor, this will be the only method that this type will contain
//Create empty constructor.
CodeConstructor viewStoringTypeConstructor = CreateConstructorForViewStoringType();
viewStoringType.Attributes = MemberAttributes.Public;
//Get an expression that expresses this instance
CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression();
string viewHash = MetadataHelper.GenerateHashForAllExtentViewsContent(edmCollection.EdmVersion, GenerateDictionaryForEntitySetNameAndView(generatedViews));
CodeAssignStatement EdmEntityContainerNameStatement =
new CodeAssignStatement(
new CodeFieldReferenceExpression(thisRef, EntityViewGenerationConstants.EdmEntityContainerName),
new CodePrimitiveExpression(edmContainerName));
CodeAssignStatement StoreEntityContainerNameStatement =
new CodeAssignStatement(
new CodeFieldReferenceExpression(thisRef, EntityViewGenerationConstants.StoreEntityContainerName),
new CodePrimitiveExpression(storeContainerName));
CodeAssignStatement HashOverMappingClosureStatement =
new CodeAssignStatement(
new CodeFieldReferenceExpression(thisRef, EntityViewGenerationConstants.HashOverMappingClosure),
new CodePrimitiveExpression(hashOverMappingClosure));
CodeAssignStatement HashOverAllExtentViewsStatement =
new CodeAssignStatement(
new CodeFieldReferenceExpression(thisRef, EntityViewGenerationConstants.HashOverAllExtentViews),
new CodePrimitiveExpression(viewHash));
CodeAssignStatement ViewCountStatement =
new CodeAssignStatement(
new CodeFieldReferenceExpression(thisRef, EntityViewGenerationConstants.ViewCountPropertyName),
new CodePrimitiveExpression(generatedViews.Count));
viewStoringTypeConstructor.Statements.Add(EdmEntityContainerNameStatement);
viewStoringTypeConstructor.Statements.Add(StoreEntityContainerNameStatement);
viewStoringTypeConstructor.Statements.Add(HashOverMappingClosureStatement);
viewStoringTypeConstructor.Statements.Add(HashOverAllExtentViewsStatement);
viewStoringTypeConstructor.Statements.Add(ViewCountStatement);
//Add the constructor to the type
//.........这里部分代码省略.........
public override object Visit(InvocationExpression invocationExpression, object data)
{
Expression target = invocationExpression.TargetObject;
CodeExpression targetExpr;
string methodName = null;
if (target == null) {
targetExpr = new CodeThisReferenceExpression();
} else if (target is FieldReferenceOrInvocationExpression) {
FieldReferenceOrInvocationExpression fRef = (FieldReferenceOrInvocationExpression)target;
targetExpr = (CodeExpression)fRef.TargetObject.AcceptVisitor(this, data);
if (fRef.TargetObject is FieldReferenceOrInvocationExpression) {
FieldReferenceOrInvocationExpression fRef2 = (FieldReferenceOrInvocationExpression)fRef.TargetObject;
if (fRef2.FieldName != null && Char.IsUpper(fRef2.FieldName[0])) {
// an exception is thrown if it doesn't end in an indentifier exception
// for example for : this.MyObject.MyMethod() leads to an exception, which
// is correct in this case ... I know this is really HACKY :)
try {
CodeExpression tExpr = ConvertToIdentifier(fRef2);
if (tExpr != null) {
targetExpr = tExpr;
}
} catch (Exception) {}
}
}
methodName = fRef.FieldName;
// HACK for : Microsoft.VisualBasic.ChrW(NUMBER)
//Console.WriteLine(methodName);
if (methodName == "ChrW") {
//Console.WriteLine("Return CAST EXPRESSION" + GetExpressionList(invocationExpression.Parameters)[0]);
return new CodeCastExpression("System.Char", GetExpressionList(invocationExpression.Parameters)[0]);
}
} else {
targetExpr = (CodeExpression)target.AcceptVisitor(this, data);
}
return new CodeMethodInvokeExpression(targetExpr, methodName, GetExpressionList(invocationExpression.Parameters));
}
/// <summary>
/// Adds an implementation of the INotifyPropertyChanged interface to the given type.
/// </summary>
/// <param name="type">The type declaration</param>
/// <returns>Type with INotifyPropertyChanged implemented.</returns>
protected CodeTypeDeclaration ImplementINotifyPropertyChanged(CodeTypeDeclaration type)
{
//// This method will implement the INotifyPropertyChanged interface
//// Here's an example :
//// public class Customer :INotifyPropertyChanged {
//// public PropertyChangedEventHandler PropertyChanged;
//// public void RaisePropertyChanged(string propertyName) {
//// if( this.PropertyChanged !=null ) {
//// this.PropertyChanged (this, new PropertyChangedEventArgs( propertyName ) );
//// }
//// }
//// }
CodeThisReferenceExpression thisReference = new CodeThisReferenceExpression();
CodeTypeReference notifyPropertyChanged = Code.TypeRef(typeof(INotifyPropertyChanged));
// Add the implements INotifyPropertyChanged statement
// public class Customer :INotifyPropertyChanged {
type.BaseTypes.Add(notifyPropertyChanged);
// Add the PropertyChanged event as a field to the type
// public PropertyChangedEventHandler PropertyChanged;
CodeMemberEvent propertyChangedEvent = type.AddEvent(Code.TypeRef(typeof(PropertyChangedEventHandler)), "PropertyChanged");
propertyChangedEvent.ImplementationTypes.Add(notifyPropertyChanged);
// this.PropertyChanged
CodeEventReferenceExpression eventFieldReference = new CodeEventReferenceExpression(thisReference, "PropertyChanged");
// Add the RaisePropertyChanged Method which will invoke the PropertyChanged handler whenever a property value changes
// if( this.PropertyChanged !=null )
CodeConditionStatement invokeEventHandlersIfAny = new CodeConditionStatement(new CodeBinaryOperatorExpression(eventFieldReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)));
// this.PropertyChanged (this, new PropertyChangedEventArgs( propertyName ) );
invokeEventHandlersIfAny.TrueStatements.Add(
new CodeDelegateInvokeExpression(eventFieldReference, new CodeExpression[] { thisReference, new CodeObjectCreateExpression("PropertyChangedEventArgs", new CodeArgumentReferenceExpression("propertyName")) }));
// public void RaisePropertyChanged
CodeMemberMethod method = type.AddMethod("RaisePropertyChanged", MemberAttributes.Public);
method.Parameters.Add(new CodeParameterDeclarationExpression("System.String", "propertyName"));
//// public void RaisePropertyChanged(string propertyName) {
//// if( this.PropertyChanged !=null ) {
//// this.PropertyChanged (this, new PropertyChangedEventArgs( propertyName ) );
//// }
//// }
method.Statements.Add(invokeEventHandlersIfAny);
return type;
}
请发表评论