Serializing a collection and comply to Code Analysis - c#

While running Code Analysis on an existing project I came across the messages Do not expose generic lists and Collection properties should be read only.
However, this class is used to read/write from/to an xml configuration file.
Is it possible to make this class comply to CA1002 and CA2227 or do I have to suppress these rules for XML-related classes (there are a lot of them in the project)?
EDIT
Changing List<string> to Collection<string> solved CA1002.
Still no clue on how to solve CA2227 and still be able to (de)serialize the whole thing.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
/// <summary>
/// Class containing the Configuration Storage
/// </summary>
[XmlRoot("Configuration")]
public class ConfigurationStorage
{
/// <summary>
/// Gets or sets the list of executers.
/// </summary>
[XmlArray("Executers")]
[XmlArrayItem("Executer")]
public Collection<string> Executers { get; set; }
/// <summary>
/// Gets or sets the list of IPG prefixes.
/// </summary>
[XmlArray("IpgPrefixes")]
[XmlArrayItem("IpgPrefix")]
public Collection<string> IpgPrefixes { get; set; }
}
Reading the xml-file:
public static ConfigurationStorage LoadConfiguration()
{
if (File.Exists(ConfigFile))
{
try
{
using (TextReader r = new StreamReader(ConfigFile))
{
var s = new XmlSerializer(typeof(ConfigurationStorage));
var config = (ConfigurationStorage)s.Deserialize(r);
return config;
}
}
catch (InvalidOperationException invalidOperationException)
{
throw new StorageException(
"An error occurred while deserializing the configuration XML file.", invalidOperationException);
}
}
}

How about:
/// <summary>
/// Class containing the Configuration Storage
/// </summary>
[XmlRoot("Configuration")]
public class ConfigurationStorage {
/// <summary>
/// Gets or sets the list of executers.
/// </summary>
[XmlArray("Executers")]
[XmlArrayItem("Executer")]
public Collection<string> Executers { get; private set; }
/// <summary>
/// Gets or sets the list of IPG prefixes.
/// </summary>
[XmlArray("IpgPrefixes")]
[XmlArrayItem("IpgPrefix")]
public Collection<string> IpgPrefixes { get; private set; }
public ConfigurationStorage() {
Executers = new Collection<string>();
IpgPrefixes = new Collection<string>();
}
}
This will still work for xml serialization/deserialization.

If you read the documentation on MSDN, you see a note:
The XmlSerializer gives special treatment to classes that implement
IEnumerable or ICollection. A class that implements IEnumerable must
implement a public Add method that takes a single parameter. The Add
method's parameter must be of the same type as is returned from the
Current property on the value returned from GetEnumerator, or one of
that type's bases. A class that implements ICollection (such as
CollectionBase) in addition to IEnumerable must have a public Item
indexed property (indexer in C#) that takes an integer, and it must
have a public Count property of type integer. The parameter to the Add
method must be the same type as is returned from the Item property, or
one of that type's bases. For classes that implement ICollection,
values to be serialized are retrieved from the indexed Item property,
not by calling GetEnumerator.
So, I think, if you fall in line with this special treatment, you'll have better code that works with XmlSerializer, doesn't use a legacy namespace, and satisfies Code Analysis warnings in the right way, rather than exploiting an oversight in the rule.
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
/// <summary>
/// Class containing the Configuration Storage
/// </summary>
[XmlRoot("Configuration")]
public class ConfigurationStorage
{
// The executers.
private readonly ICollection<string> executers = new List<string>();
// The IPG prefixes.
private readonly ICollection<string> ipgPrefixes = new List<string>();
/// <summary>
/// Gets the list of executers.
/// </summary>
[XmlArray("Executers")]
[XmlArrayItem("Executer")]
public ICollection<string> Executers
{
get
{
return this.executers;
}
}
/// <summary>
/// Gets the list of IPG prefixes.
/// </summary>
[XmlArray("IpgPrefixes")]
[XmlArrayItem("IpgPrefix")]
public ICollection<string> IpgPrefixes
{
get
{
return this.ipgPrefixes;
}
}
}

Related

Inaccessible due to protection level in C#

I have references object which contains abstract LoggerFile class. I am trying to access it. But it is showing inaccessible due to protection level. Please anyone help me to understand it.
abstract class LoggerFile
{
private static String logFile = null;
/// <summary>
/// Logfile Property
/// </summary>
public static string LogFile { get => logFile; set => logFile = value; }
/// <summary>
/// Set logFile
/// </summary>
/// <param name="logFile">The absolute path to file for writting logs</param>
public static void SetLogFile(String logFile)
{
LogFile = LogFile ?? logFile;
if (!File.Exists(LogFile))
{
File.Create(LogFile).Close();
}
}
}
}
I am calling this in another class.
using DriverAutomation.Loggin[enter image description here][1]g;
public class Devcon
{
private static Devcon devcon = null;
private readonly String devconEXE;
private readonly String devconPath;
private readonly String devconExeName;
private readonly Logger logger;
/// <summary>
/// DevconStatus Property for devcon status outcome backup
/// </summary>
public readonly String devconStatus;
/// <summary>
/// Initializes the Devcon Singleton Instance
/// </summary>
private Devcon()
{
devcon = this;
logger = Logger.GetLogger(GetType().Name, LoggerFile.LogFile);
devconExeName = "devcon.exe";
devconEXE = Path.Combine(Directory.GetCurrentDirectory(), devconExeName);
}
}
This is working within created solution. But using reference object it is showing error. Please find image.
Declare your class as public and non-Abstract and I think it will solve your problem.
public class LoggerFile
By the way, why is it even Abstract. If you only have some static members in it, maybe you should just turn it to static itself.
Though in most logger implementations, it makes sense to follow the singleton pattern (one of the few cases)

deriving a class from another class causes Com registration error

I have a project that follows WPF/MVVM pattern. I have tried to derive my ViewModel class from PropertyChangedBase so that I can Notify of data changes to the view. As soon as I derive the class from PropertyChangeBase and compile, I get error saying
Error 1 Cannot register assembly "D:\Source\ArcOnline\bin\Debug\ArcOnline.dll". Could not load file or assembly 'Major, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
here is how my class is defined
using ArcOnline.WPF;
using System;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ArcOnline.ViewModels
{
/// <summary>
/// The class handles the template for a single
/// </summary>
public class TemplatesViewModel : PropertyChangedBase
{
/// <summary>
///
/// </summary>
public ArcOnlineViewModel ArcManager { get; set; }
private string _layerID;
/// <summary>
/// Layer ID
/// </summary>
public string LayerID
{
get { return _layerID; }
set { _layerID = value; NotifyOfPropertyChange(() => LayerID); }
}
private string _title;
/// <summary>
/// Title of the layer
/// </summary>
public string Title
{
get { return _title; }
set { _title = value; NotifyOfPropertyChange(() => Title); }
}
............. More properties as above
}
and here is the how my PropertyChangedBase is defined
using Component.Linq.Expressions;
using System;
using System.Collections;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using System.Xml.Serialization;
#endregion
namespace Component.ComponentModel
{
/// <summary>
/// A base class from which ViewModels can inherit to improve the quality of
/// patterns such as INotifyPropertyChanged.
/// </summary>
[DataContract]
[Serializable]
public class PropertyChangedBase : INotifyPropertyChanged, INotifyDataErrorInfo, IDataErrorInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertyChangedBase"/> class.
/// </summary>
public PropertyChangedBase()
{
ErrorsChanged += Notify_ErrorChanged;
}
void Notify_ErrorChanged(object sender, DataErrorsChangedEventArgs e)
{
NotifyOfPropertyChange(() => Error);
}
...... More class definition continues
}
This PropertyChangedBase is actually defined in a different Project so that is why it has all the header files included. If I copy the code of this PropertyChangedBase class and create a new class in my own Project where TemplatesViewModel is defined and then use it, it works perfectly fine.
I just want to know what is the reason for it not working in the first case?? This wasted my whole day!!
Thanks in advance

exposing .Net to COM

I have some .Net functionality I am trying to use in VB6. I have followed several tutorials. I wrote a test program with success using the formula here: http://www.codeproject.com/Articles/3511/Exposing-NET-Components-to-COM
However, when I try to do it with my actual project, my ProgId doesn't show in the registry like my test file. I made sure property ComVisible == true
using System.Runtime.InteropServices;
namespace Controls.Graph.Web
{
[Guid("5F9F6C6F-016A-4CFF-BD7A-3463761807E1")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _GraphScript
{
[DispId(1)]
string getGraphXml();
}
[Guid("35901BC6-EFF1-490C-84FA-786E8462C553")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId(ProgIds.GraphScript)]
public class GraphScript : _GraphScript
{
protected GraphScript()
{
}
/// <summary>
///
/// </summary>
/// <returns>The graphs xml and javascript</returns>
public string getGraphXml()
{
DisplayDefaults tempDefaults;
tempDefaults = new DisplayDefaults();
GraphConstructor graph = new GraphConstructor();
graph.constructGraph();
GraphModel completedGraph = graph.Graph;
return GraphControl.RenderGraph(completedGraph, tempDefaults, 1) + GraphControl.RenderGraphScript();
}
}
}
and my progid...
using System;
namespace Controls.Graph.Web
{
/// <summary>
/// ProgID Constant
/// </summary>
public static class ProgIds
{
public const string GraphScript = "GraphData";
}
}
I'm not sure which piece of the puzzle I'm missing here
EDIT: actually the Guid shows up in the registry however the Progid still is not. Any ideas/suggestions?
also made sure to do this:
I have figured out what was wrong. I needed to change some access modifiers to PUBLIC -- including my GraphScript() constructor.

How is the Memento Pattern implemented in C#4?

The Memento Pattern itself seems pretty straight forward. I'm considering implementing the same as the wikipedia example, but before I do are there any language features of C# that make it easier to implement or use?
One obvious feature would be generics, implementing an generic memento will allow you to use it for any object you want.
Many examples that you will see will use a string (including all those currently among the replies to this question) as state which is a problem since it's one of the few types in .NET which are immutable.
When dealing with mutable objects (like any reference type with a setter-property) you have to remember though that when you save the memento you need to create a deepcopy of the object. Otherwise whenever you change your original object you will change your memento.
You could do this by using a serializer like protobuf-net or json.net since they don't require you to mark your objects with serializable attribute like the normal .net serialization mechanism does.
Codeproject have few articles about generic memento implementations, but they tend to skip the deepcopy part:
Generic Memento Pattern for Undo-Redo in C#
Memento Design Pattern
I'm not aware of any already built-in way to support Memento pattern.
I see a couple of implementations by using .NET Mock frameworks, where in practise a clone of the object is created and can be field with a data, but I consider it kind of overhead.
The use Memento patter on Undo/Redo usually, probably you too. In this case, it's better to have as less data on Undo/Redo stack as possible, so the custom undoable object is something that I would go for.
Hope this helps.
There is one thing that will make this pattern marginally quicker to write in C# and that is that any state fields can be declared as public readonly so you don't need properties or 'get' methods to access them.
Here is a straight conversion with public readonly included.
class Originator
{
private string state;
// The class could also contain additional data that is not part of the
// state saved in the memento.
public void Set(string state)
{
Console.WriteLine("Originator: Setting state to " + state);
this.state = state;
}
public Memento SaveToMemento()
{
Console.WriteLine("Originator: Saving to Memento.");
return new Memento(state);
}
public void RestoreFromMemento(Memento memento)
{
state = memento.SavedState;
Console.WriteLine("Originator: State after restoring from Memento: " + state);
}
public class Memento
{
public readonly string SavedState;
public Memento(string stateToSave)
{
SavedState = stateToSave;
}
}
}
class Caretaker
{
static void Main(string[] args)
{
List<Originator.Memento> savedStates = new List<Originator.Memento>();
Originator originator = new Originator();
originator.Set("State1");
originator.Set("State2");
savedStates.Add(originator.SaveToMemento());
originator.Set("State3");
// We can request multiple mementos, and choose which one to roll back to.
savedStates.Add(originator.SaveToMemento());
originator.Set("State4");
originator.RestoreFromMemento(savedStates[1]);
}
}
I've found one using Generics here:
#region Originator
public class Originator<T>
{
#region Properties
public T State { get; set; }
#endregion
#region Methods
/// <summary>
/// Creates a new memento to hold the current
/// state
/// </summary>
/// <returns>The created memento</returns>
public Memento<T> SaveMemento()
{
return (new Memento<T>(State));
}
/// <summary>
/// Restores the state which is saved in the given memento
/// </summary>
/// <param name="memento">The given memento</param>
public void RestoreMemento(Memento<T> memento)
{
State = memento.State;
}
#endregion
}
#endregion
#region Memento
public class Memento<T>
{
#region Properties
public T State { get; private set; }
#endregion
#region Ctor
/// <summary>
/// Construct a new memento object with the
/// given state
/// </summary>
/// <param name="state">The given state</param>
public Memento(T state)
{
State = state;
}
#endregion
}
#endregion
#region Caretaker
public class Caretaker<T>
{
#region Properties
public Memento<T> Memento { get; set; }
#endregion
}
#endregion
#region Originator
public class Originator<T>
{
#region Properties
public T State { get; set; }
#endregion
#region Methods
/// <summary>
/// Creates a new memento to hold the current
/// state
/// </summary>
/// <returns>The created memento</returns>
public Memento<T> SaveMemento()
{
return (new Memento<T>(State));
}
/// <summary>
/// Restores the state which is saved in the given memento
/// </summary>
/// <param name="memento">The given memento</param>
public void RestoreMemento(Memento<T> memento)
{
State = memento.State;
}
#endregion
}
#endregion
#region Memento
public class Memento<T>
{
#region Properties
public T State { get; private set; }
#endregion
#region Ctor
/// <summary>
/// Construct a new memento object with the
/// given state
/// </summary>
/// <param name="state">The given state</param>
public Memento(T state)
{
State = state;
}
#endregion
}
#endregion
#region Caretaker
public class Caretaker<T>
{
#region Properties
public Memento<T> Memento { get; set; }
#endregion
}
#endregion
Used like this:
Originator<string> org = new Originator<string>();
org.State = "Old State";
// Store internal state in the caretaker object
Caretaker<string> caretaker = new Caretaker<string>();
caretaker.Memento = org.SaveMemento();
Console.WriteLine("This is the old state: {0}", org.State);
org.State = "New state";
Console.WriteLine("This is the new state: {0}", org.State);
// Restore saved state from the caretaker
org.RestoreMemento(caretaker.Memento);
Console.WriteLine("Old state was restored: {0}", org.State);
// Wait for user
Console.Read();
As #Simon Skov Boisen mentions this will only work for immutable data and requires a deep copy.

Class designs with collections within them, with collections within those

In a continuation of my previous thread, I have found that a lot of my classes contain collections. Eg:
Engine - contains collection of pistons - piston - contains collection of xyz parts
Thus there is a hierarchy, as every component contains a collection of parts, which goes on and on.
This is a coding scenario I have not come across before. Constantly writing code like so:
class Part (Replace Part with apt name)
{
List<APart> parts ...
}
And then the same for APart, as that contains a collection of inner parts, is very tedious and therefore making me question whether this is the right way to code.
Is there a better way to write this sort of code? Anything like AOP etc I am open to (Though AOP is for cross-cutting concerns).
One thought:
Your Engine class could contain a PistonsManager class, which manages the list of Pistons. The PistonsManager could contain all of the logic to modify the list and shield the Engine class from having to think about Pistons. By the same logic, your PistonsManager class could contain an XYZPartsManager. This way you aren't programming list logic/management into your Engine logic, but have classes to do that. It might make readability and make the logic flow nicely.
Sometimes coding is just tedious. However, there are often patterns that can be ferreted out of an implementation.
We have a situation similar to yours and discovered that there was an underlying recursive pattern. So we implemented a base class (call it Part) that itself can contain a List(Of Part). This can be as deep as needed.
The collection classes for specific class implementations are either generic collections of the specific type or implement an interface that allows us to get at specific data in the class (we had to implement the interface mechanism due to collection collisions in WCF).
The upshot is that you will probably have a lot of discrete Part inheritors, but your will will be a common way to instantiate, process, and traverse your elements with a common set of code.
Update
This is a severely contrived example, but one that should get you pointed in the right direction. In our application, we use a substantial amount of reflection and table-mapped class names in order to severely reduce the amount of repetitive code. This example reflects some of that behavior, but not all.
This example basically shows how you can have a generic part class which contains a recursive collection of parts which are indexed at the part type level. In other words, you will have Engine and Engine will have a collection of part collections indexed by part type. For example, Engine could have a collection of Pistons, a collection of hoses, etc. This design is obviously optional, but does make it somewhat easier to process.
Here are the main classes:
/// <summary>
/// The base part collection
/// </summary>
/// <remarks></remarks>
public class PartBase
{
/// <summary>
/// The key for the record, such as a recordid
/// </summary>
/// <value></value>
/// <returns></returns>
/// <remarks></remarks>
public virtual string CollectionKey {get; set;}
public PartBase() : base()
{
m_cParts = new PartBaseCollections();
}
public virtual void InitializeFromDataRow(DataRow oRow)
{
// ToDo: Either implement generic column/datarow mapping through reflection or have each class override this method
}
private PartBaseCollections m_cParts;
public PartBaseCollections Parts
{
get
{
return m_cParts;
}
}
public PartBaseCollection GetParts(string sTableName)
{
if (this.Parts.Contains(sTableName))
{
return this.Parts(sTableName);
}
else
{
PartBaseCollection cParts = new PartBaseCollection(sTableName);
this.Parts.Add(cParts);
return cParts;
}
}
public void AddParts(DataSet dsData)
{
foreach (DataTable oTable in dsData.Tables)
{
PartBaseCollection cParts = null;
cParts = GetParts(oTable.TableName);
cParts.AddRecordsFromTable(oTable);
}
}
}
/// <summary>
/// A collection of PartBases keyed by a value, such as a table name (for example, Pistons)
/// </summary>
/// <remarks></remarks>
public class PartBaseCollection : System.Collections.ObjectModel.KeyedCollection<string, PartBase>
{
public string CollectionKey {get; set;}
public Type RecordType {get; set;}
public PartBaseCollection(string TableName)
{
this.CollectionKey = TableName;
// Assume that the TableName is a class in the current namespace
RecordType = Type.GetType(this.GetType().Namespace + "." + TableName, false, true);
}
protected override string GetKeyForItem(PartBase item)
{
return item.CollectionKey;
}
public PartBase ManufactureRecord()
{
return Activator.CreateInstance(this.RecordType);
}
public void AddRecordsFromTable(DataTable oTable)
{
foreach (DataRow oRow in oTable.Rows)
{
PartBase oPart = null;
oPart = ManufactureRecord();
oPart.InitializeFromDataRow(oRow);
this.Add(oPart);
}
}
}
/// <summary>
/// All of the PartBaseCollection elements for a given PartBase
/// </summary>
/// <remarks></remarks>
public class PartBaseCollections : System.Collections.ObjectModel.KeyedCollection<string, PartBaseCollection>
{
protected override string GetKeyForItem(PartBaseCollection item)
{
return item.CollectionKey;
}
}
public class Engine : PartBase
{
}
public class Piston : PartBase
{
}
And here is an example of creating the engine:
public void CreateEngine()
{
DataSet dsData = new DataSet();
DataTable oTable = new DataTable("Piston");
dsData.Tables.Add(oTable);
Engine oEngine = new Engine();
oEngine.AddParts(dsData);
}
sounds like the composite design pattern - consider looking at the iterator design pattern and perhaps the visitor design pattern as these usually go together.

Categories