Looking for another way to implement

Looking for another way to implement

Old forum URL: forums.lhotka.net/forums/t/1269.aspx


DeHaynes posted on Tuesday, September 19, 2006

   In my first foray into the CSLA framework, I hacked the framework to get the functionality I was looking for.  One of the things I did was add the capability for records to be marked inactive.  This allowed the records to continue to exist for historical purposes but also removed them from mainstream processing.  I did this by hacking the DataPortal classes as follows:

   I added the following to the client side DataPortal

/// <summary>
/// Called by the business object's Save() method to
/// deactivate an object in the database.
/// </summary>
/// <remarks>
/// Note that this method returns a reference to the updated business object.
/// If the server-side DataPortal is running remotely, this will be a new and
/// different object from the original, and all object references MUST be updated
/// to use this new object.
/// </remarks>
/// <typeparam name="T">Specific type of the business object.</typeparam>
/// <param name="obj">A reference to the business object to be updated.</param>
/// <returns>A reference to the updated business object.</returns>

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")][System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "Framework.DataPortalException.#ctor(System.String,System.Exception,System.Object)")]
public static T Deactivate<T>(T obj)
{
   
return (T)Deactivate((object)obj);
}

/// <summary>
/// Called by the business object's Save() method to deactivate an object in the database.
/// </summary>
/// <remarks>
/// Note that this method returns a reference to the updated business object.
/// If the server-side DataPortal is running remotely, this will be a new and
/// different object from the original, and all object references MUST be updated
/// to use this new object.
/// </remarks>
/// <param name="obj">A reference to the business object to be updated.</param>
/// <returns>A reference to the updated business object.</returns>

public static object Deactivate(object obj)
{
   Server.
DataPortalResult result;
   
MethodInfo method = MethodCaller.GetMethod(obj.GetType(), "DataPortal_Deactivate");
   DataPortalClient.
IDataPortalProxy proxy;
   proxy = GetDataPortalProxy(RunLocal(method));
   Server.
DataPortalContext dpContext = new Server.DataPortalContext(GetPrincipal(), proxy.IsServerRemote);
   OnDataPortalInvoke(
new DataPortalEventArgs(dpContext));

   try
   {
      result = proxy.Deactivate(obj, dpContext);
   }

   catch (Server.DataPortalException ex)
   {
      result = ex.Result;
      
if (proxy.IsServerRemote)
         
ApplicationContext.SetGlobalContext(result.GlobalContext);

      throw new DataPortalException("DataPortal.Update " + Resources.Failed, ex.InnerException, result.ReturnObject);
   }

   if (proxy.IsServerRemote)
      
ApplicationContext.SetGlobalContext(result.GlobalContext);
   OnDataPortalInvokeComplete(new DataPortalEventArgs(dpContext));
   return result.ReturnObject;
}

/// <summary>
/// Called by the business object's Save() method to re-activate an object in the database.
/// </summary>
/// <remarks>
/// Note that this method returns a reference to the updated business object.
/// If the server-side DataPortal is running remotely, this will be a new and
/// different object from the original, and all object references MUST be updated
/// to use this new object.
/// </remarks>
/// <param name="obj">A reference to the business object to be updated.</param>
/// <returns>A reference to the updated business object.</returns>

public static object Reactivate(object obj)
{
   Server.DataPortalResult result;
   MethodInfo method = MethodCaller.GetMethod(obj.GetType(), "DataPortal_Reactivate");
   DataPortalClient.IDataPortalProxy proxy;
   proxy = GetDataPortalProxy(RunLocal(method));
   Server.
DataPortalContext dpContext = new Server.DataPortalContext(GetPrincipal(), proxy.IsServerRemote);
   OnDataPortalInvoke(new DataPortalEventArgs(dpContext));

   try
   
{
      result = proxy.Reactivate(obj, dpContext);
   }

   catch (Server.DataPortalException ex)
   {
      result = ex.Result;
      if (proxy.IsServerRemote)
         
ApplicationContext.SetGlobalContext(result.GlobalContext);   

      throw new DataPortalException("DataPortal.Update " + Resources.Failed, ex.InnerException, result.ReturnObject);
   }

   if (proxy.IsServerRemote)
      
ApplicationContext.SetGlobalContext(result.GlobalContext);

   OnDataPortalInvokeComplete(new DataPortalEventArgs(dpContext));
   return result.ReturnObject;
}

 

I added the following to the server side DataPortal

/// <summary>
/// Deactivates a business object.
/// </summary>
/// <param name="criteria">Criteria object describing business object.</param>
/// <param name="context">
/// <see cref="Server.DataPortalContext" /> object passed to the server.
/// </param>

public DataPortalResult Deactivate(object obj, DataPortalContext context)
{
   
try
   
{
      SetContext(context);
      DataPortalResult result;
      MethodInfo method = MethodCaller.GetMethod(obj.GetType(), "DataPortal_Deactivate");
      IDataPortalServer portal;
      switch (TransactionalType(method))
      {
         
case TransactionalTypes.EnterpriseServices:
            
portal = new ServicedDataPortal();

            try
            
{
               result = portal.Deactivate(obj, context);
            }
            finally
            
{
               ((
ServicedDataPortal)portal).Dispose();
            }
            break;

         case TransactionalTypes.TransactionScope:
            portal =
new TransactionalDataPortal();
            result = portal.Deactivate(obj, context);
            break;

         default:
            portal =
new SimpleDataPortal();
            result = portal.Deactivate(obj, context);
            break;
      }
      return result;
   }

   finally
   
{
      ClearContext(context);
   }
}

/// <summary>
/// Re-activates a business object.
/// </summary>
/// <param name="criteria">Criteria object describing business object.</param>
/// <param name="context">
/// <see cref="Server.DataPortalContext" /> object passed to the server.
/// </param>

public DataPortalResult Reactivate(object obj, DataPortalContext context)
{
   
try
   
{
      SetContext(context);
      DataPortalResult result;
      MethodInfo method = MethodCaller.GetMethod(obj.GetType(), "DataPortal_Reactivate");
      IDataPortalServer portal;
      switch (TransactionalType(method))
      {
         
case TransactionalTypes.EnterpriseServices:
            portal =
new ServicedDataPortal();

            try
            
{
               result = portal.Reactivate(obj, context);
            }
            finally
            
{
               ((
ServicedDataPortal)portal).Dispose();
            }
            break;

         case TransactionalTypes.TransactionScope:
            portal =
new TransactionalDataPortal();
            result = portal.Reactivate(obj, context);
            break;
         
default:
            portal =
new SimpleDataPortal();
            result = portal.Reactivate(obj, context);
            break;
      }

      return result;
   }

   finally
   
{
      ClearContext(context);
   }
}

I am now trying to subclass the framework.  Can anyone think of a way to subclass the frame work and still have this functionality?  I can't think of a way without making my own DataPortals.

DeHaynes replied on Tuesday, September 19, 2006

Is it possible to partial class from a different project?

So if I create a Partial Class for Both the client and server DataPortals and only put in it the code I need to add my functionality.  Then in the future when a new version of CSLA comes out, I only have to go modify the DataPortal Classes and make them partial classes.

DeHaynes replied on Tuesday, September 19, 2006

After further review, I have custom code in the following classes

namespace Csla

public static class DataPortal
public abstract class EnterpriseServicesProxy
public class LocalProxy
public class RemotingProxy
public class WebServicesProxy

namespace Csla.Server.Hosts

public abstract class EnterpriseServicesPortal
public class RemotingPortal

namespace Csla.Server

public class DataPortal
public interface IDataPortalServer
public class ServicedDataPortal
public class SimpleDataPortal
public class TransactionalDataPortal

My solution so far has been to make them all partial classes, so I can move my custom code to their own files.  I have run into a snag,  "public class WebServicePortal".  In my hacked up version I had to resort to some trickery to get the class customized.  Is there any way to partial the class so I can add my custom code?

DeHaynes replied on Tuesday, September 19, 2006

Specifically my issue I am having is with WebServiceHost under web references.  I need to add some items too it.

DeactivateCompletedEventArgs
DactivateCompletedEventHander

ReactivateCompletedEventArgs
RactivateCompletedEventHander

 

I am not not familiar with web services.  Is there some way to partial this reference too?

DeHaynes replied on Tuesday, September 19, 2006

I think I will start a seperate post.  I have this pretty much nailed down to a certain area AND the echo in here is too much.

Copyright (c) Marimer LLC