# 19 Ağustos 2006 Cumartesi

It's a black hole since its so massive that even a tiny piece of information on it's usage cannot escape out. Start writing an addin for Visual Studio and you'll find lots of information on the net. Enter into realms of Server Explorer, and you'll feel the massive darkness.

I'm coding and addin for Visual Studio 2005 using DSL Tools. Apart from the relatively steep learning curve of DSL Tools, it was going fine. By the very nature of the project, I started thinking on adding drag and drop of tables from Server Explorer. There are some DSRef and UIHierarchy usage examples on the net, so I thought it will be a piece of cake, until I find out there's no simple way of getting the underlying object model for data connections in Server Explorer, thanks to Microsoft's ability to mark everything Server Explorer as Private or Internal.

Long story short, after long nights and hours of Reflector and thousands of evasive maneuvers against the missile fired by my wife, here's how you get the DbConnection instance of Server Explorer holding the tables dropped on your design surface:

        private static DataConnection GetDataConnection(DTE dte, string itemName)

        {

            IntPtr ptr = IntPtr.Zero;

            try

            {

                if (((IServiceProvider)dte).QueryService(ref ServerExplorer, ref IUnknown, out ptr) >= 0)

                {

                    object o = Marshal.GetObjectForIUnknown(ptr);

                    if (o != null)

                    {

                        object dataConnectionsNode = GetField(o, "lastBrowseObjectNodeSite");

                        if (dataConnectionsNode != null)

                        {

                            INodeSite nodeSite =

                                (INodeSite)dataConnectionsNode;

 

                            INodeSite[] nodes = nodeSite.FindChildrenByLabel(itemName);

                            if (nodes != null && nodes.Length > 0)

                            {

                                object expNode = GetField(nodes[0], "expNode");

                                if (expNode != null)

                                {

                                    object nestedHierarchy = GetField(expNode, "nestedHierarchy");

                                    if (nestedHierarchy != null)

                                    {

                                        DataConnection connection =

                                            GetProperty(nestedHierarchy, "DataConnection") as DataConnection;

                                        if (connection != null)

                                        {

                                            return connection;

                                        }

                                    }

                                }

                            }

                        }

                    }

                }

            }

            finally

            {

                Marshal.Release(ptr);

            }

 

            return null;

        }

        private static object GetField(object o, string fieldName)

        {

            if (o != null && !String.IsNullOrEmpty(fieldName))

                return o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(o);

 

            return null;

        }

 

        private static object GetProperty(object o, string fieldName)

        {

            if (o != null && !String.IsNullOrEmpty(fieldName))

                return o.GetType().GetProperty(fieldName).GetValue(o, null);

 

            return null;

        }

Once you get DataConnection, try ConnectionSupport.ProviderObject property to get the actual DbConnection. Happily, VS loaded addins cannot load new assemblies into AppDomain but at least allowed reflection.