/// <summary> /// Konvertiert einen Ausdruck und liefert einen Expression Model zurück. /// </summary> /// <param name="expression">Der zu konvertierende Ausdruck.</param> /// <param name="element">Das element an dem der Kontrakt definiert wurde.</param> /// <returns>Ein Expression Model.</returns> internal ExpressionModel ConvertExpression(string expression, MemberInfo element) { if (String.IsNullOrEmpty(expression)) throw new NullReferenceException(Resources.ExcContractIsNull); if (element == null) throw new NullReferenceException(Resources.ExcContractedMemberIsNull); // this. ist ein zugriff auf ein Klassenelement this. kann jedoch nicht aufgelöst werden // daher wird this. entfernt. expression.Replace("this.", ""); // Wenn es sich um einen Generics Typ handelt müssen alle Generics Parameter ersetzt werden. if (element.DeclaringType.IsGenericType) { mGenericParameter = new List<string>(); Type[] genericTypes = element.DeclaringType.GetGenericArguments(); foreach (Type genericParameterType in genericTypes) { if (genericParameterType.IsGenericParameter) mGenericParameter.Add(genericParameterType.Name); else throw new ArgumentException (string.Format(CultureInfo.CurrentCulture, Resources.ExcNoGenericParameter, new object[]{genericParameterType})); } } // die Liste für den Zugriff auf gespeicherte (alte) Werte zurücksetzen. mOldValueExpressions = new List<string>(); ExpressionModel exprModel = new ExpressionModel(expression, element, mGenericParameter); exprModel.ConvertedExpression = GetConvertedExpression(expression, element); if (mOldValueExpressions.Count > 0) { mOldValueExpressions.Insert(0, "object[] " + Resources.StrParameterOldValues + " = new object[" + mOldValueExpressions.Count + "]"); mOldValueExpressions.Add("return " + Resources.StrParameterOldValues ); foreach (string oldValue in mOldValueExpressions) exprModel.OldValueAccessExpression += "\r\n" + oldValue; exprModel.SetGetOldValueExpression(mOldValueExpressions); } return exprModel; }
/// <summary> /// Prüft ob der übergebene Ausdruck ein Type ist und setzt alle Typbasierten Paramter. /// Wenn der übergebene Ausdruck kein Type ist wird null zurückgegeben. /// </summary> /// <param name="expression">Der zu prüfende Ausdruck</param> /// <returns>Ein ExpressionModel wenn der übergebene Ausdruck ein Type ist, andernfalls null </returns> private ExpressionModel ConvertToTypedExpression(ExpressionModel expression) { Type convertedType = AssemblyController.Instance.FindTypeInAssemblyAndAllReferences(expression.Expression, expression.DeclaringType.Assembly); if (convertedType != null) { expression.ExpressionType = convertedType; expression.ConvertedExpression = expression.ExpressionType.FullName; return expression; } return null; }
/// <summary> /// Konvertiert einen Ausdruck zu einem Arrayzugriff. Das Array repräsentiert alle Werte die /// mit [old] gekennzeichnet wurden. /// </summary> /// <param name="expression">Der zu konvertierende Ausdruck</param> /// <param name="convertToType">Gibt an ob der Zugriff auf das OldValue Array typisiert werden soll</param> /// <returns>Das ExpressionModel mit zugriff auf das OldValue Array</returns> private ExpressionModel GetOldValueExpression(ExpressionModel expression, bool convertToType) { mOldValueExpressions.Add(Resources.StrParameterOldValues+"[" + mOldValueExpressions.Count.ToString() + "] = " + expression.ConvertedExpression); expression.OldValueAccessExpression = expression.ConvertedExpression; string typOfValue = (convertToType&& expression.ExpressionType != null) ? expression.ExpressionType.FullName : string.Empty; expression.ConvertedExpression = GetArrayExpression(typOfValue, Resources.StrParameterOldValues, (mOldValueExpressions.Count-1)); return expression; }
/// <summary> /// Prüft ob der übergebene Ausdruck ein String ist und setzt alle Typbasierten Paramter. /// Wenn der übergebene Ausdruck kein String ist wird null zurückgegeben. /// </summary> /// <param name="expression">Der zu prüfende Ausdruck</param> /// <returns>Ein ExpressionModel wenn der übergebene Ausdruck ein String ist, andernfalls null </returns> private ExpressionModel ConvertToStringExpression(ExpressionModel expression) { if ((expression.Expression.StartsWith("\"")) && (expression.Expression.EndsWith("\""))) { expression.ExpressionType = typeof(string); expression.ConvertedExpression = expression.Expression; return expression; } return null; }
/// <summary> /// Prüft ob der übergebene Ausdruck ein Public Member der Klasse, in der der Kontrakt /// angegenben ist und setzt alle Typbasierten Paramter. Wenn der übergebene Ausdruck /// kein Public Member der Klasse, in der der Kontrakt angegenben ist wird null /// zurückgegeben. /// </summary> /// <param name="expression">Der zu prüfende Ausdruck</param> /// <returns>Ein ExpressionModel wenn der übergebene Ausdruck ein Public Member der Klasse, /// in der der Kontrakt angegenben ist, andernfalls null </returns> private ExpressionModel ConvertToPublicMemberExpression(ExpressionModel expression) { // Wenn der Typ in dem der Kontrakt definiert ist schon nicht Public ist, muss via Reflection // Auf das Element zugegriffen werden. if (!expression.DeclaringType.IsPublic) return ConvertToPrivateMemberExpression(expression, BindingFlags.Public | BindingFlags.Instance); MemberInfo[] memberInfos = null; // BUG PostSharp Version 1.5 liefert nicht die Mitglieder zurück. // MemberInfo[] memberInfos = null; // memberInfos = expression.DeclaringType.GetMember(expression.Expression, BindingFlags.Public | BindingFlags.Instance); // Workaround MemberInfo tempMemberInfo = GetMemberInfo(expression.Expression, expression.DeclaringType, BindingFlags.Public | BindingFlags.Instance); if (tempMemberInfo != null) memberInfos = new MemberInfo[] { tempMemberInfo }; if ((memberInfos != null) && (memberInfos.Length > 0)) { if (memberInfos.Length != 1) throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.ExcMorePublicMemberFound, new object[] { expression.Expression })); MemberInfo memberInfo = memberInfos[0]; if (memberInfo is PropertyInfo) { if (((PropertyInfo)memberInfo).GetGetMethod(true) != null) expression.ExpressionType = ((PropertyInfo)memberInfo).GetGetMethod(true).ReturnType; else throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.ExcNoGetMethodAvailable, new object[] { ((PropertyInfo)memberInfo).Name })); } else if (memberInfo is MethodInfo) { if (((MethodInfo)memberInfo).ReturnType != null) expression.ExpressionType = ((MethodInfo)memberInfo).ReturnType; else throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.ExcMethodIsVoid, new object[] { ((MethodInfo)memberInfo).Name })); } else if (memberInfo is FieldInfo) expression.ExpressionType = ((FieldInfo)memberInfo).FieldType; string expressionType = expression.ExpressionType.FullName; if (string.IsNullOrEmpty(expressionType)) expressionType = "object"; expression.ConvertedExpression = "(("+expression.DeclaringType+")" + Resources.StrParameterInstance + ")." + expression.Expression; return expression; } return null; }
/// <summary> /// Prüft ob der übergebene Ausdruck ein Private Member der Klasse, in der der Kontrakt /// angegenben ist und setzt alle Typbasierten Paramter. Wenn der übergebene Ausdruck /// kein Private Member der Klasse, in der der Kontrakt angegenben ist wird null /// zurückgegeben. /// </summary> /// <param name="expression">Der zu prüfende Ausdruck</param> /// <returns>Ein ExpressionModel wenn der übergebene Ausdruck ein Private Member der Klasse, /// in der der Kontrakt angegenben ist, andernfalls null </returns> private ExpressionModel ConvertToPrivateMemberExpression(ExpressionModel expression, BindingFlags bindingFlags) { // Sucht ob expression der Name einer privaten Methode ist. MethodInfo method = null; // BUG PostSharp Version 1.5 liefert nicht die Methoden zurück. // method = expression.DeclaringType.GetMethod(expression.Expression, bindingFlags); // woraround method = GetMethodInfo(expression.Expression, expression.DeclaringType, bindingFlags); string memberType = string.Empty; if (method != null) { if (method.ReturnType != null) expression.ExpressionType = method.ReturnType; else throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.ExcMethodIsVoid, new object[] { method.Name })); memberType = expression.ExpressionType.FullName; if (string.IsNullOrEmpty(memberType)) memberType = "object"; expression.ConvertedExpression = "((" + memberType + ")(" + Resources.StrParameterInstance + ".GetType().GetMethod(\"" + expression.Expression + "\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(" + Resources.StrParameterInstance + ", "; expression.IsPrivateMethod = true; return expression; } // Sucht ob expression der Name einer privaten Eigenschaft ist. PropertyInfo property = null; // BUG PostSharp Version 1.5 liefert nicht die Eigenschaften zurück. // property = expression.DeclaringType.GetProperty(expression.Expression, bindingFlags); // Woraround property = GetPropertyInfo(expression.Expression, expression.DeclaringType, bindingFlags); if (property != null) { Type propertyType = null; if (property.GetGetMethod(true) != null) propertyType = property.GetGetMethod(true).ReturnType; else throw new Exception(string.Format ( CultureInfo.CurrentCulture, Resources.ExcNoGetMethodAvailable, new object[]{property.Name})); expression.ExpressionType = propertyType; memberType = expression.ExpressionType.FullName; if (string.IsNullOrEmpty(memberType)) memberType = "object"; expression.ConvertedExpression = "((" + memberType + ")(" + Resources.StrParameterInstance + ".GetType().GetProperty(\"" + expression.Expression + "\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue( " + Resources.StrParameterInstance + ", null )))"; return expression; } // Sucht ob expression der Name eines privaten Feldes ist. FieldInfo field = null; // BUG PostSharp Version 1.5 liefert nicht die Felder zurück. // field = expression.DeclaringType.GetField(expression.Expression, bindingFlags); // Workaround field = GetFieldInfo(expression.Expression, expression.DeclaringType, bindingFlags); if (field != null) { expression.ExpressionType = field.FieldType; memberType = expression.ExpressionType.FullName; if (string.IsNullOrEmpty(memberType)) memberType = "object"; expression.ConvertedExpression = "((" + memberType + ")(" + Resources.StrParameterInstance + ".GetType().GetField(\"" + expression.Expression + "\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue( " + Resources.StrParameterInstance + " )))"; return expression; } return null; }
/// <summary> /// Prüft ob der übergebene Ausdruck ein Übergabeparameter ist und setzt alle Typbasierten Paramter. /// Wenn der übergebene Ausdruck kein Übergabeparameter ist wird null zurückgegeben. /// </summary> /// <param name="expression">Der zu prüfende Ausdruck</param> /// <returns>Ein ExpressionModel wenn der übergebene Ausdruck ein Übergabeparameter ist, andernfalls null </returns> private ExpressionModel ConvertToParameterExpression(ExpressionModel expression) { ParameterInfo[] parameterInfos = null; if (expression.Element is MethodInfo) parameterInfos = ((MethodInfo)expression.Element).GetParameters(); else if (expression.Element is PropertyInfo) parameterInfos = ((PropertyInfo)expression.Element).GetSetMethod(true).GetParameters(); if (parameterInfos == null) return null; foreach (ParameterInfo paraInfo in parameterInfos) { if (paraInfo.Name == expression.Expression) { expression.ExpressionType = paraInfo.ParameterType; expression.ConvertedExpression = GetArrayExpression(paraInfo.ParameterType.FullName, Resources.StrParameterContractArguments, paraInfo.Position); return expression; } } return null; }
/// <summary> /// Typisiert den übergebenen Ausdruck. /// </summary> /// <param name="expression">Der zu Typisierende Ausdruck.</param> /// <param name="element">Element an dem der Kontrakt definiert wurde.</param> /// <returns> /// Ein ExpressionModel mit dem übersetzten Ausdruck. Wenn der Ausdruck nicht Typisiert /// werden konnte wird einfach der originale Wert zum konventierten.</returns> private ExpressionModel ConvertElementExpression(string expression, MemberInfo element) { ExpressionModel elementExpressionModel = new ExpressionModel(expression, element, mGenericParameter); // Wenn das Model aus welchem Grund auch immer nicht Konvertiert werden soll, einfach // zurückgeben if (elementExpressionModel.DontConvert) return elementExpressionModel; // wenn expression ein Reservierter ausdruck ist einfach zurückgeben. if (IsDefinedExpression(elementExpressionModel.Expression)) { elementExpressionModel.ConvertedExpression = elementExpressionModel.Expression; return elementExpressionModel; } // Prüfen ob der Ausdruck ein String ist. ExpressionModel checkExprnMdl = ConvertToStringExpression(elementExpressionModel); if (checkExprnMdl != null) return checkExprnMdl; // Prüfen ob der Ausdruck ein Übergabeparameter ist. checkExprnMdl = ConvertToParameterExpression(elementExpressionModel); if (checkExprnMdl != null) { if (checkExprnMdl.IsOldValueAccess) checkExprnMdl = GetOldValueExpression(checkExprnMdl, true); return checkExprnMdl; } // Prüfen ob der Ausdruck ein zugriff auf einen public Member der Klasse ist, in der der // Kontrakt definiert ist. checkExprnMdl = ConvertToPublicMemberExpression(elementExpressionModel); if (checkExprnMdl != null) { if (checkExprnMdl.IsOldValueAccess) checkExprnMdl = GetOldValueExpression(checkExprnMdl, true); return checkExprnMdl; } // Prüfen ob der Ausdruck ein zugriff auf einen private Member der Klasse ist, in der der // Kontrakt definiert ist. checkExprnMdl = ConvertToPrivateMemberExpression(elementExpressionModel, BindingFlags.NonPublic | BindingFlags.Instance ); if (checkExprnMdl != null) { if (checkExprnMdl.IsOldValueAccess) checkExprnMdl = GetOldValueExpression(checkExprnMdl, true); return checkExprnMdl; } checkExprnMdl = ConvertToTypedExpression(elementExpressionModel); if (checkExprnMdl != null) return checkExprnMdl; // Da der Ausdruck nicht übersetzt werden konnte wird der Original Ausdruck gesetzt. elementExpressionModel.ConvertedExpression = elementExpressionModel.Expression; return elementExpressionModel; }