Files
PowerShell/src/System.Management.Automation/engine/COM/ComAdapter.cs
T

345 lines
14 KiB
C#

/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.ComponentModel;
using Microsoft.PowerShell;
#if CORECLR
using System.Reflection;
#endif
namespace System.Management.Automation
{
/// <summary>
/// Implements Adapter for the COM objects.
/// </summary>
internal class ComAdapter : Adapter
{
private readonly ComTypeInfo _comTypeInfo;
/// <summary>
/// Constructor for the ComAdapter
/// </summary>
/// <param name="typeinfo">typeinfo for the com object we are adapting</param>
internal ComAdapter(ComTypeInfo typeinfo)
{
Diagnostics.Assert(typeinfo != null, "Caller to verify typeinfo is not null.");
_comTypeInfo = typeinfo;
}
internal static string GetComTypeName(string clsid)
{
StringBuilder firstType = new StringBuilder("System.__ComObject");
firstType.Append("#{");
firstType.Append(clsid);
firstType.Append("}");
return firstType.ToString();
}
/// <summary>
/// Returns the TypeNameHierarchy out of an object
/// </summary>
/// <param name="obj">object to get the TypeNameHierarchy from</param>
protected override IEnumerable<string> GetTypeNameHierarchy(object obj)
{
yield return GetComTypeName(_comTypeInfo.Clsid);
foreach (string baseType in GetDotNetTypeNameHierarchy(obj))
{
yield return baseType;
}
}
/// <summary>
/// Returns null if memberName is not a member in the adapter or
/// the corresponding PSMemberInfo
/// </summary>
/// <param name="obj">object to retrieve the PSMemberInfo from</param>
/// <param name="memberName">name of the member to be retrieved</param>
/// <returns>The PSMemberInfo corresponding to memberName from obj</returns>
protected override T GetMember<T>(object obj, string memberName)
{
ComProperty prop;
if (_comTypeInfo.Properties.TryGetValue(memberName, out prop))
{
if (prop.IsParameterized)
{
if (typeof(T).IsAssignableFrom(typeof(PSParameterizedProperty)))
{
return new PSParameterizedProperty(prop.Name, this, obj, prop) as T;
}
}
else if (typeof(T).IsAssignableFrom(typeof(PSProperty)))
{
return new PSProperty(prop.Name, this, obj, prop) as T;
}
}
ComMethod method;
if (typeof(T).IsAssignableFrom(typeof(PSMethod)) &&
(_comTypeInfo != null) && (_comTypeInfo.Methods.TryGetValue(memberName, out method)))
{
PSMethod mshMethod = new PSMethod(method.Name, this, obj, method);
return mshMethod as T;
}
return null;
}
/// <summary>
/// Retrieves all the members available in the object.
/// The adapter implementation is encouraged to cache all properties/methods available
/// in the first call to GetMember and GetMembers so that subsequent
/// calls can use the cache.
/// In the case of the .NET adapter that would be a cache from the .NET type to
/// the public properties and fields available in that type.
/// In the case of the DirectoryEntry adapter, this could be a cache of the objectClass
/// to the properties available in it.
/// </summary>
/// <param name="obj">object to get all the member information from</param>
/// <returns>all members in obj</returns>
protected override PSMemberInfoInternalCollection<T> GetMembers<T>(object obj)
{
PSMemberInfoInternalCollection<T> collection = new PSMemberInfoInternalCollection<T>();
bool lookingForProperties = typeof(T).IsAssignableFrom(typeof(PSProperty));
bool lookingForParameterizedProperties = typeof(T).IsAssignableFrom(typeof(PSParameterizedProperty));
if (lookingForProperties || lookingForParameterizedProperties)
{
foreach (ComProperty prop in _comTypeInfo.Properties.Values)
{
if (prop.IsParameterized)
{
if (lookingForParameterizedProperties)
{
collection.Add(new PSParameterizedProperty(prop.Name, this, obj, prop) as T);
}
}
else if (lookingForProperties)
{
collection.Add(new PSProperty(prop.Name, this, obj, prop) as T);
}
}
}
bool lookingForMethods = typeof(T).IsAssignableFrom(typeof(PSMethod));
if (lookingForMethods)
{
foreach (ComMethod method in _comTypeInfo.Methods.Values)
{
if (collection[method.Name] == null)
{
PSMethod mshmethod = new PSMethod(method.Name, this, obj, method);
collection.Add(mshmethod as T);
}
}
}
return collection;
}
/// <summary>
/// Returns an array with the property attributes
/// </summary>
/// <param name="property">property we want the attributes from</param>
/// <returns>an array with the property attributes</returns>
protected override AttributeCollection PropertyAttributes(PSProperty property)
{
return new AttributeCollection();
}
/// <summary>
/// Returns the value from a property coming from a previous call to DoGetProperty
/// </summary>
/// <param name="property">PSProperty coming from a previous call to DoGetProperty</param>
/// <returns>The value of the property</returns>
protected override object PropertyGet(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.GetValue(property.baseObject);
}
/// <summary>
/// Sets the value of a property coming from a previous call to DoGetProperty
/// </summary>
/// <param name="property">PSProperty coming from a previous call to DoGetProperty</param>
/// <param name="setValue">value to set the property with</param>
/// <param name="convertIfPossible">instructs the adapter to convert before setting, if the adapter supports conversion</param>
protected override void PropertySet(PSProperty property, object setValue, bool convertIfPossible)
{
ComProperty prop = (ComProperty)property.adapterData;
prop.SetValue(property.baseObject, setValue);
}
/// <summary>
/// Returns true if the property is settable
/// </summary>
/// <param name="property">property to check</param>
/// <returns>true if the property is settable</returns>
protected override bool PropertyIsSettable(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsSettable;
}
/// <summary>
/// Returns true if the property is gettable
/// </summary>
/// <param name="property">property to check</param>
/// <returns>true if the property is gettable</returns>
protected override bool PropertyIsGettable(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsGettable;
}
/// <summary>
/// Returns the name of the type corresponding to the property
/// </summary>
/// <param name="property">PSProperty obtained in a previous DoGetProperty</param>
/// <param name="forDisplay">True if the result is for display purposes only</param>
/// <returns>the name of the type corresponding to the property</returns>
protected override string PropertyType(PSProperty property, bool forDisplay)
{
ComProperty prop = (ComProperty)property.adapterData;
return forDisplay ? ToStringCodeMethods.Type(prop.Type) : prop.Type.FullName;
}
/// <summary>
/// get the property signature.
/// </summary>
/// <param name="property">property object whose signature we want</param>
/// <returns>string representing the signature of the property</returns>
protected override string PropertyToString(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.ToString();
}
#region Methods
/// <summary>
/// Called after a non null return from GetMethodData to try to call
/// the method with the arguments
/// </summary>
/// <param name="method">the non empty return from GetMethods</param>
/// <param name="arguments">the arguments to use</param>
/// <returns>the return value for the method</returns>
protected override object MethodInvoke(PSMethod method, object[] arguments)
{
ComMethod commethod = (ComMethod)method.adapterData;
return commethod.InvokeMethod(method, arguments);
}
/// <summary>
/// Called after a non null return from GetMethodData to return the overloads
/// </summary>
/// <param name="method">the return of GetMethodData</param>
/// <returns></returns>
protected override Collection<String> MethodDefinitions(PSMethod method)
{
ComMethod commethod = (ComMethod)method.adapterData;
return commethod.MethodDefinitions();
}
#endregion
#region parameterized property
/// <summary>
/// Returns the name of the type corresponding to the property's value
/// </summary>
/// <param name="property">property obtained in a previous GetMember</param>
/// <returns>the name of the type corresponding to the member</returns>
protected override string ParameterizedPropertyType(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.Type.FullName;
}
/// <summary>
/// Returns true if the property is settable
/// </summary>
/// <param name="property">property to check</param>
/// <returns>true if the property is settable</returns>
protected override bool ParameterizedPropertyIsSettable(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsSettable;
}
/// <summary>
/// Returns true if the property is gettable
/// </summary>
/// <param name="property">property to check</param>
/// <returns>true if the property is gettable</returns>
protected override bool ParameterizedPropertyIsGettable(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsGettable;
}
/// <summary>
/// Called after a non null return from GetMember to get the property value
/// </summary>
/// <param name="property">the non empty return from GetMember</param>
/// <param name="arguments">the arguments to use</param>
/// <returns>the return value for the property</returns>
protected override object ParameterizedPropertyGet(PSParameterizedProperty property, object[] arguments)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.GetValue(property.baseObject, arguments);
}
/// <summary>
/// Called after a non null return from GetMember to set the property value
/// </summary>
/// <param name="property">the non empty return from GetMember</param>
/// <param name="setValue">the value to set property with</param>
/// <param name="arguments">the arguments to use</param>
protected override void ParameterizedPropertySet(PSParameterizedProperty property, object setValue, object[] arguments)
{
ComProperty prop = (ComProperty)property.adapterData;
prop.SetValue(property.baseObject, setValue, arguments);
}
/// <summary>
/// Returns the string representation of the property in the object
/// </summary>
/// <param name="property">property obtained in a previous GetMember</param>
/// <returns>the string representation of the property in the object</returns>
protected override string ParameterizedPropertyToString(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.ToString();
}
/// <summary>
/// Called after a non null return from GetMember to return the overloads
/// </summary>
/// <param name="property">the return of GetMember</param>
protected override Collection<String> ParameterizedPropertyDefinitions(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
Collection<string> returnValue = new Collection<string> { prop.GetDefinition() };
return returnValue;
}
#endregion parameterized property
}
}