I have a class that is public, ArticleDao, but when I try to use it in another file, it says "ArticleDao is inaccessible due to its protection level." Here is the entire class:
class ArticleDao : IArticleDao
{
private readonly ContentManager _contentManager;
private static readonly char[] DelimiterChars = { '|', '\n' };
private const int ArticlePagingSize = 500;
public ArticleDao()
{
_contentManager = new ContentManager();
}
private Image GetImage(XElement element)
{
var image = new Image();
if (String.IsNullOrEmpty((String)element))
{
return image;
}
XElement imageElement = element.Element("img");
if (imageElement != null)
{
image.Url = (String)imageElement.Attribute("src");
}
return image;
}
private Link GetLink(XElement element)
{
var link = new Link();
if (String.IsNullOrEmpty((String)element))
{
return link;
}
XElement anchorElement = element.Element("a");
if (anchorElement != null)
{
link.Url = (String)anchorElement.Attribute("href");
link.Text = (String)anchorElement;
}
return link;
}
public Article GetArticle(long id, string html)
{
var a = new Article();
long testid = 556;
if (id == testid)
{
var x = 1;
}
XDocument xdoc = XDocument.Parse(html);
var xElement = xdoc.Element("root");
if (xElement != null)
{
XElement articleElem = xElement.Element("Event");
if (articleElem != null)
{
a = new Article();
a.Id = id.ToString(CultureInfo.InvariantCulture);
a.Title = (String)articleElem.Element("Title");
a.PublishedDate = GetDateTime((String)articleElem.Element("PublishedDate"));
a.SubHeader = (String)articleElem.Element("SubHeader");
a.Image = GetImage(articleElem.Element("Image"));
a.Caption = (String)articleElem.Element("Caption");
a.Body = (String)articleElem.Element("Body");
a.Url = GetLink(articleElem.Element("Url"));
}
}
return a;
}
public Article GetArticle(Int64 ektronContentId)
{
var item = _contentManager.GetItem(ektronContentId);
return GetArticle(ektronContentId, item.Html);
}
public IEnumerable<Article> GetArticles(Int64 folderId)
{
int count;
IEnumerable<Article> articles = new List<Article>(ArticlePagingSize);
do
{
var criteria = new ContentCriteria();
criteria.AddFilter(ContentProperty.FolderId, CriteriaFilterOperator.EqualTo, folderId);
criteria.PagingInfo.RecordsPerPage = ArticlePagingSize;
var articleContentData = _contentManager.GetList(criteria);
count = articleContentData == null ? 0 : articleContentData.Count;
articles = articles.Concat(_contentManager.GetList(criteria)
.Select(i => GetArticle(i.Id, i.Html)));
} while (count == ArticlePagingSize);
return articles;
}
private DateTime GetDateTime(string date)
{
DateTime dt;
DateTime.TryParse(date, out dt);
return dt;
}
}
The constructor is public. I even tried replacing all instances of "private" with "public," but it still says that it is inaccessible. This is the line where I'm trying to invoke it:
private static IArticleDao _articleDao;
public static IArticleDao ArticleDao
{
get { return _articleDao ?? (_articleDao = new ArticleDao()); }
}
Where it says "_articleDao = new ArticleDao()" is where the error is.
I'm especially confused because to create ArticleDao and IArticleDao, I essentially just copied EventDao and IEventDao and replaced "Event" with "Article." This works:
private static IEventDao _eventDao;
public static IEventDao EventDao
{
get { return _eventDao ?? (_eventDao = new EventDao()); }
}
but ArticleDao does not work.
The class itself isn't public. It's internal. (The default accessibility for anything is the smallest legal accessibility option, which for a non-nested class, is internal. You have specified no accessibility option explicitly.)
You class ArticleDao is a internal, as if you don't specify any accessibility modifier, the default in C# is internal. To resolve this issue you may think of declaring it public
public class ArticleDao : IArticleDao
{
...
}
The class' default access level is internal. Internal types or members are accessible only within files in the same assembly.
You probably want to specify
public class ArticleDao...
The constructor accessibility is not the same as the class access level, and if something is hidden by the class access modifier you cannot access any of its members regardless of their access modifier.
Related
I can not figure out how to prevent code dublication for that code block.
There is a base class That is Base_Reader and derived types like JT_Reader, IGES_Reader etc.
But base class dont have methods that childs have. Also I can not Change these because they come with dll.
Here are code sample;
string aModelExpansion = Path.GetExtension(filePath).ToLower();
if (aModelExpansion == "jt")
{
var aReader = ModelReaderFactory.CreateReader<JT_Reader>();
//Remaining parts are exactly same, I just need to use aReader according to my extension.
var aReaderParamaters = aReader.Parameters();
aReaderParamaters.SetDelayedConversion(Settings.DelayedConversion);
aReader.ReadFile(new Base_UTF16String(filePath));
//convert STEP to MDM
ModelData_Model aLoadedModel = new ModelData_Model();
var s = aReader.Transfer(aLoadedModel);
//convert MDM to GameObject
Unity_ObjectFactory aConventer = new Unity_ObjectFactory();
string aModelName = filePath.Split('/')[filePath.Split('/').Length - 1];
_meshParentGameObject = aConventer.Create(aLoadedModel, aModelName);
yield return new WaitUntil(() => _meshParentGameObject != null);
}
if (aModelExpansion == "iges")
{
var aReader = ModelReaderFactory.CreateReader<IGES_Reader>();
var aReaderParamaters = aReader.Parameters();
aReaderParamaters.SetDelayedConversion(Settings.DelayedConversion);
aReader.ReadFile(new Base_UTF16String(filePath));
//convert STEP to MDM
ModelData_Model aLoadedModel = new ModelData_Model();
var s = aReader.Transfer(aLoadedModel);
//convert MDM to GameObject
Unity_ObjectFactory aConventer = new Unity_ObjectFactory();
string aModelName = filePath.Split('/')[filePath.Split('/').Length - 1];
_meshParentGameObject = aConventer.Create(aLoadedModel, aModelName);
yield return new WaitUntil(() => _meshParentGameObject != null);
}
// Generic type creator
public static T CreateReader<T>() where T : Base_Reader, new()
{
return new T();
}
//Method signatures for readers
// public JT_ReaderParameters Parameters() => new JT_ReaderParameters(CadExJTPINVOKE.JT_Reader_Parameters(this.swigCPtr), true);
// public IGES_ReaderParameters Parameters() => new IGES_ReaderParameters(CadExIGESPINVOKE.IGES_Reader_Parameters(this.swigCPtr), true);
I dont want to create code blocks for all my model extensions.
Any help would be appreciated!
I would probably use the Template Pattern here.
Start out by creating a base class with the shared algorithm and some algorithm identifier, as well as a common interface. I would just use the name as the identifer, just like you have been doing.
public interface IExpander
{
string Identifier { get; }
IEnumerable<WaitUntil> Read(string filePath);
}
public abstract class BaseExpander<T> : IExpander where T : Base_Reader
{
public abstract string Identifier { get; }
public abstract T CreateReader();
public IEnumerable<WaitUntil> Read(string filePath)
{
var reader = CreateReader();
var aReaderParamaters = reader.Parameters();
aReaderParamaters.SetDelayedConversion(Settings.DelayedConversion);
reader.ReadFile(new Base_UTF16String(filePath));
//convert STEP to MDM
ModelData_Model aLoadedModel = new ModelData_Model();
var s = reader.Transfer(aLoadedModel);
//convert MDM to GameObject
Unity_ObjectFactory aConventer = new Unity_ObjectFactory();
string aModelName = filePath.Split('/')[filePath.Split('/').Length - 1];
_meshParentGameObject = aConventer.Create(aLoadedModel, aModelName);
yield return new WaitUntil(() => _meshParentGameObject != null);
}
/* not sure what these are only added them here to compile*/
private object _meshParentGameObject;
public IConfiguration Settings { get; private set; }
}
After that, I would then create the specialized expanders, one for each type. So, two like so:
public class JTExpander : BaseExpander<JT_Reader>
{
public override string Identifier => "jt";
public IModelReaderFactory ModelReaderFactory { get; }
public JTExpander(IModelReaderFactory ModelReaderFactory)
{
this.ModelReaderFactory = ModelReaderFactory;
}
public override JT_Reader CreateReader()
=> ModelReaderFactory.CreateReader<JT_Reader>();
}
public class IGESExpander : BaseExpander<IGES_Reader>
{
public override string Identifier => "iges";
public IModelReaderFactory ModelReaderFactory { get; }
public IGESExpander(IModelReaderFactory ModelReaderFactory)
{
this.ModelReaderFactory = ModelReaderFactory;
}
public override IGES_Reader CreateReader()
=> ModelReaderFactory.CreateReader<IGES_Reader>();
}
In order to use them, I would have to have something that knows about all expanders and can decide which one to use. So a factory seems like a nice fit. Small note, I would usually use dependency injection here and register all implementations of BaseExpander in the IoC container, and the create a dictionary out of them with the identifier as key. I'll leave that up to you as an exercise. My factory would look something like this:
public class ExpanderFactory
{
private IEnumerable<IExpander> expanders;
public ExpanderFactory()
{
IModelReaderFactory factory = new ModelReaderFactory();
expanders = new List<IExpander>
{
new JTExpander(factory),
new IGESExpander(factory)
};
}
IExpander GetExpander(string expansionIdentifier)
=> expanders.First(x => x.Identifier == expansionIdentifier);
}
Finally, stitching it all together, it would look something like this:
public class SomeParentProcess
{
ExpanderFactory factory = new ExpanderFactory();
public void Expand(string path)
{
var extension = Path.GetExtension(path).ToLower();
var expander = factory.GetExpander(extension);
foreach (var expansion in expander.Read(path))
{
//Let's go!
}
}
}
There is definitely room for improvement, but I hope you get the jist.
If there are any other details that differ between the expanders, you can create another abstract method in the BaseExpander class and have the specialized expanders do whatever needs to be done. You can call the new abstract method from the abstract BaseExpander class since you require anyone that inherits that class implements that method as well. You can always use the reader in its full potential from the specialized class since it is part of the class's type argument.
Let's pretend that JT used base16 for its file encoding and that IGES used base8. We would then change the BaseExpander class to look like this:
public abstract class BaseExpander<T> : IExpander where T : Base_Reader
{
public abstract string Identifier { get; }
public abstract T CreateReader();
public abstract void ReadFile(T reader, string path);
public IEnumerable<WaitUntil> Read(string filePath)
{
var reader = CreateReader();
var aReaderParamaters = reader.Parameters();
aReaderParamaters.SetDelayedConversion(Settings.DelayedConversion);
//Here, it used to be reader.ReadFile(new Base_UTF16String(filePath));
ReadFile(reader, filePath);
//convert STEP to MDM
ModelData_Model aLoadedModel = new ModelData_Model();
var s = reader.Transfer(aLoadedModel);
//convert MDM to GameObject
Unity_ObjectFactory aConventer = new Unity_ObjectFactory();
string aModelName = filePath.Split('/')[filePath.Split('/').Length - 1];
_meshParentGameObject = aConventer.Create(aLoadedModel, aModelName);
yield return new WaitUntil(() => _meshParentGameObject != null);
}
/* not sure what these are only added them here to compile*/
private object _meshParentGameObject;
public IConfiguration Settings { get; private set; }
}
And now, the specialized classes look like this:
public class JTExpander : BaseExpander<JT_Reader>
{
public override string Identifier => "jt";
public IModelReaderFactory ModelReaderFactory { get; }
public JTExpander(IModelReaderFactory ModelReaderFactory)
{
this.ModelReaderFactory = ModelReaderFactory;
}
public override JT_Reader CreateReader()
=> ModelReaderFactory.CreateReader<JT_Reader>();
public override void ReadFile(JT_Reader reader, string path)
{
reader.ReadFile(new Base_UTF16String(path));
}
}
public class IGESExpander : BaseExpander<IGES_Reader>
{
public override string Identifier => "iges";
public IModelReaderFactory ModelReaderFactory { get; }
public IGESExpander(IModelReaderFactory ModelReaderFactory)
{
this.ModelReaderFactory = ModelReaderFactory;
}
public override IGES_Reader CreateReader()
=> ModelReaderFactory.CreateReader<IGES_Reader>();
public override void ReadFile(IGES_Reader reader, string path)
{
reader.ReadFile(new Base_UTF8String(path));
}
}
Thank you for your answers again. I solved it with dynamic types. Where I changed reader and readerParameters variables as dynamic.
if (brepFormats.Contains(aModelExpansion))
{
dynamic aReader = ModelReaderFactory.CreateModelReader(aModelExpansion);
if (aReader == null)
{
Debug.LogError("Haha you get runtime error if you use dynamic...");
yield break;
}
dynamic aReaderParamaters = aReader.Parameters();
aReaderParamaters.SetDelayedConversion(Settings.DelayedConversion);
aReader.ReadFile(new Base_UTF16String(filePath));
//convert STEP to MDM
ModelData_Model aLoadedModel = new ModelData_Model();
var s = aReader.Transfer(aLoadedModel);
//convert MDM to GameObject
Unity_ObjectFactory aConventer = new Unity_ObjectFactory();
string aModelName = filePath.Split('/')[filePath.Split('/').Length - 1];
_meshParentGameObject = aConventer.Create(aLoadedModel, aModelName);
yield return new WaitUntil(() => _meshParentGameObject != null);
}
public class ModelReaderFactory
{
public static dynamic CreateModelReader(string aModelExpansion)
{
dynamic aReader = null;
if (aModelExpansion == ".jt")
aReader = CreateReader<JT_Reader>();
if(aModelExpansion == ".step")
aReader = CreateReader<STEP_Reader>();
if(aModelExpansion == ".rhino")
aReader = CreateReader<Rhino_Reader>();
if(aModelExpansion == ".dwg")
aReader = CreateReader<DWG_Reader>();
if(aModelExpansion == ".nx")
aReader = CreateReader<NX_Reader>();
if(aModelExpansion == ".solidworks")
aReader = CreateReader<SLD_Reader>();
if (aModelExpansion == ".iges")
aReader = CreateReader<IGES_Reader>();
if (aModelExpansion == ".ifc")
aReader = CreateReader<IFC_Reader>();
if (aModelExpansion == ".acis")
aReader = CreateReader<ACIS_Reader>();
if (aModelExpansion == ".parasolid")
aReader = CreateReader<Para_Reader>();
if (aModelExpansion == ".catia")
aReader = CreateReader<CAT_Reader>();
if (aModelExpansion == ".creo")
aReader = CreateReader<Creo_Reader>();
return aReader;
}
private static T CreateReader<T>() where T : Base_Reader, new()
{
return new T();
}
}
I want to set some data in an API class by calling a function from another class.
Why the 'main' has error while 'Classes' works? How and where I should define it?
Error: a field initializer cannot reference the nonstatic field
How do I can get the ID which has passed in URL to use in my class?
This is my code:
public class InformationController : ApiController
{
Classes main = new Classes();
Information[] Information = new Information[]
{
new Information { Info_ID = 2, fullName = main.getFullname("2"), },
};
public IEnumerable<Information> GetAllInformation()
{
return Information;
}
public Information GetInformationById(int id)
{
var information = Information.FirstOrDefault((p) => p.Info_ID == id);
if (information == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return information;
}
public IEnumerable<Information> GetInformationByCategory(string category)
{
return Information.Where(
(p) => string.Equals(p.std_nextClass, category,
StringComparison.OrdinalIgnoreCase));
}
}
You can try initialize the array in the constructor:
public class InformationController : ApiController
{
private Classes main = new Classes();
private Information[] Information;
public InformationController()
{
Information = new Information[]
{
new Information { Info_ID = 2, fullName = main.getFullname("2"), },
};
}
/// the rest of your code...
I've been looking for a way to make a table like thing in C# (3.5), but still have come up empty. Basically I want to do this
var myClassVar = new myClass();
myClassVar["hello"]["world"] = "hello world";
myClassVar["hello"][0] = "swapped";
myClassVar[0][0] = "test";
myClassVar["hello"]["to"]["the"]["world"] = "again";
myClassVar[0][1][0][0] = "same as above sorta";
I'm trying to create this type of class to parse a file format I've created for storing data. Does anyone know of something like this?
public class LuaTable
{
private Dictionary<object, dynamic> properties = new Dictionary<object, dynamic>();
public dynamic this[object property]
{
get
{
if (properties.ContainsKey(property))
return properties[property];
LuaTable table = new LuaTable();
properties.Add(property, table);
return table;
}
set
{
if (!properties.ContainsKey(property))
properties.Add(property, value);
else
properties[property] = value;
}
}
}
You can use it exactly how you want to:
var myClassVar = new LuaTable();
myClassVar["hello"]["world"] = "hello world";
myClassVar["hello"][0] = "swapped";
myClassVar[0][0] = "test";
myClassVar["hello"]["to"]["the"]["world"] = "again";
myClassVar[0][1][0][0] = "same as above sorta";
string s1 = myClassVar["hello"]["world"]; // = "hello world"
string s2 = myClassVar["hello"][0]; // = "swapped"
string s3 = myClassVar[0][0]; // = "test"
string s4 = myClassVar["hello"]["to"]["the"]["world"]; // = "again"
string s5 = myClassVar[0][1][0][0]; // = "same as above sorta"
Edit: I just realized C# 3.5 doesn't have dynamic, so here's a version that simply uses generics. I hope that this is fine (since you really have to have all of the child properties of your table be of the same type (in this case, string):
public class LuaTable<T> where T : class
{
private bool isValue;
private T value = null;
private Dictionary<object, LuaTable<T>> properties = new Dictionary<object, LuaTable<T>>();
public static implicit operator LuaTable<T>(T val)
{
if (val is LuaTable<T>)
return (LuaTable<T>)val;
return new LuaTable<T>() { isValue = true, value = val };
}
public static implicit operator T(LuaTable<T> table)
{
if (table.isValue)
return table.value;
return table;
}
public LuaTable<T> this[object property]
{
get
{
if (isValue)
return null;
if (properties.ContainsKey(property))
return properties[property];
LuaTable<T> table = new LuaTable<T>();
properties.Add(property, table);
return table;
}
set
{
if (!properties.ContainsKey(property))
properties.Add(property, value);
else
properties[property] = value;
}
}
}
To use it, it's almost exactly the same as above. Just change the first line:
var myClassVar = new LuaTable<string>();
Here is the code snippet from my LinqPad:
public class Elephant{
public int Size;
public Elephant()
{
Size = 1;
}
}
public struct Ant{
public int Size;
}
private T[] Transform2AnotherType<T>(Elephant[] elephantList)
where T:new()
{
dynamic tArray = new T[elephantList.Length];
for (int i = 0; i < elephantList.Length; i++)
{
tArray[i] = new T();
tArray[i].Size = 100;
//tArray[i].Dump();
}
return tArray;
}
void Main()
{
var elephantList = new Elephant[2];
var elephant1 = new Elephant();
var elephant2 = new Elephant();
elephantList[0] = elephant1;
elephantList[1] = elephant2;
elephantList.Dump();
var r = Transform2AnotherType<Ant>(elephantList);
r.Dump();
}
I want to change one object array of known type,Elephant,to another object array of type T. T is not a class,but limited to struct which
provided by the already existed API.And every instance of type T shares some common property,says Size,but also has their own particular property which
I have omitted in my example code.So I put dynamic keyword inside the Transform2AnotherType<T>.
And I could not even to use Dump to make sure if the assignment has made effect,thus will throw RuntimeBinderException.
My question is: how to correctly make the assignment in such a struct array and return it back properly?
I suggest change your code like this:
public class Elephant
{
public Elephant()
{
Size = 1;
}
public int Size { get; set; }
}
public struct Ant
{
public int Size { get; set; }
}
private static T[] Transform2AnotherType<T>(Elephant[] elephantList)
where T : new()
{
T[] tArray = new T[elephantList.Length];
for (int i = 0; i < elephantList.Length; i++)
{
dynamic arrayElement = new T();
arrayElement.Size = 100;
tArray[i] = arrayElement;
//tArray[i].Dump();
}
return tArray;
}
static void Main()
{
var elephantList = new Elephant[2];
var elephant1 = new Elephant();
var elephant2 = new Elephant();
elephantList[0] = elephant1;
elephantList[1] = elephant2;
//elephantList.Dump();
var r = Transform2AnotherType<Ant>(elephantList);
//r.Dump();
}
I have this class:
using System.IO;
using System.Xml.Serialization;
namespace ssscc.Settings
{
public class AppSettings
{
private string _companyName;
public string CompanyName
{
set { _companyName = value; }
get
{
if (string.IsNullOrWhiteSpace(_companyName))
{
LoadSettings();
}
return _companyName;
}
}
private string _companyPhone;
public string CompanyPhone
{
set
{
_companyPhone = value;
}
get
{
if (string.IsNullOrWhiteSpace(_companyPhone))
{
LoadSettings();
}
return _companyPhone;
}
}
private string GetSettingsFile()
{
var exePath = System.Windows.Forms.Application.StartupPath;
var sharedDirectory = Path.Combine(exePath, "shared");
var settingsDirectory = Path.Combine(sharedDirectory, "settings");
var settingsFile = Path.Combine(settingsDirectory, "ssscc.xml");
if (!Directory.Exists(sharedDirectory))
{
Directory.CreateDirectory(sharedDirectory);
}
if (!Directory.Exists(settingsDirectory))
{
Directory.CreateDirectory(settingsDirectory);
}
return settingsFile;
}
internal void SaveSettings(AppSettings settings)
{
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenWrite(GetSettingsFile()))
{
serializer.Serialize((Stream) stream, (object) settings);
}
}
internal void LoadSettings()
{
if (!File.Exists(GetSettingsFile()))
{
return;
}
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenRead(GetSettingsFile()))
{
var appsetting = (AppSettings) serializer.Deserialize(stream);
CompanyPhone = appsetting.CompanyPhone;
CompanyName = appsetting.CompanyName;
}
}
}
}
My question is about this code:
var appsetting = (AppSettings) serializer.Deserialize(stream);
CompanyPhone = appsetting.CompanyPhone;
CompanyName = appsetting.CompanyName;
I am pretty sure there is a way to return the appsettings directly to the class that contains the method so I do not have to loop through each property such as this:
CompanyPhone = appsetting.CompanyPhone;
CompanyName = appsetting.CompanyName;
Can I assign the properties directly without having to maintain this code?
You are getting a new instance of AppSettings while deserializing from file. You may use it, can't you? Try to replace LoadSettings with a static factory method like this:
internal static AppSettings GetInstance()
{
if (!File.Exists(GetSettingsFile()))
return null;
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenRead(GetSettingsFile()))
return (AppSettings)serializer.Deserialize(stream);
}
while to save your settings, you have no need to pass the settings object as an argument. I guess the following code should do the job:
internal void SaveSettings()
{
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenWrite(GetSettingsFile()))
serializer.Serialize((Stream)stream, this);
}
Use the factory GetInstance method to initialize settings (well, as an example):
var s = AppSettings.GetInstance();
if (s == null)
{
s = new AppSettings
{
CompanyName = "MyCompany",
CompanyPhone = "######"
};
s.SaveSettings();
}
P.S.: if properties getters and setters have no additional logic (LoadSettings method no longer exists), you could use auto-properties:
public string CompanyName { get; set; }
public string CompanyPhone { get; set; }
and GetSettingsFile may be declared as static, as it does not operate any of the instance class members:
private static string GetSettingsFile()
{
//...
return settingsFile;
}
Do you really need to have lazy-loading in here, if not, make your methods explicitly:
public class AppSettings
{
private static readonly XmlSerializer Serializer
= new XmlSerializer(typeof(AppSettings));
public string CompanyName { get; set; }
public string CompanyPhone { set; get; }
private static string GetSettingsFile()
{
return null;
}
public static void SaveSettings(AppSettings settings)
{
using (var stream = File.OpenWrite(GetSettingsFile()))
Serializer.Serialize(stream, settings);
}
internal static AppSettings LoadSettings()
{
if (!File.Exists(GetSettingsFile()))
return null;
object appsetting = null;
using (var stream = File.OpenRead(GetSettingsFile()))
appsetting = Serializer.Deserialize(stream);
return appsetting as AppSettings;
}
}
Do you can use:
var setting = AppSettings.LoadSettings();
and:
AppSettings.SaveSettings(setting);
Please note in here, creating XmlSerializer everytime will get the memory leak,
The XmlSerializer constructor will generate a pair of classes derived from XmlSerializationReader and XmlSerializationWriter by analyzing the Person class using reflection. It will create temporary C# files, compile the resulting files into a temporary assembly, and finally load that assembly into the process. Code gen like this is also relatively expensive. So the XmlSerializer caches the temporary assemblies on a per-type basis. This means that the next time an XmlSerializer for the Person class is created, the cached assembly is used rather than a new one generated.
Therefore, you should keep XmlSerializer as static.