Да, необходимо создать NSAutoreleasePool
в Вашем [NSOperation main]
метод, если Вы не создаете "параллельное" (немного неудачная номенклатура) NSOperation
подкласс и Ваш переопределенный [NSOperation start]
, метод создает NSAutoreleasePool
прежде, чем назвать' [NSOperation основным].
NSOperation
документация класса имеет хорошее описание всего этого: http://developer.apple.com/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html .
Это зависит от того, для чего вам нужен тип MIME. В общем, для служб (веб-приложения, веб-службы и т. Д.) Рекомендуется не использовать список MIME, который зависит от настроек ОС, или только в качестве запасного варианта, если иначе вы не можете найти информацию MIME.
Я думаю, что это также причина, по которой MS решила поместить постоянные типы MIME в свой класс System.Web.MimeMapping
(к сожалению, он внутренний по какой-то причине).
Изменить:
public static class MimeExtensionHelper
{
static object locker = new object();
static object mimeMapping;
static MethodInfo getMimeMappingMethodInfo;
static MimeExtensionHelper()
{
Type mimeMappingType = Assembly.GetAssembly(typeof(HttpRuntime)).GetType("System.Web.MimeMapping");
if (mimeMappingType == null)
throw new SystemException("Couldnt find MimeMapping type");
ConstructorInfo constructorInfo = mimeMappingType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
if (constructorInfo == null)
throw new SystemException("Couldnt find default constructor for MimeMapping");
mimeMapping = constructorInfo.Invoke(null);
if (mimeMapping == null)
throw new SystemException("Couldnt find MimeMapping");
getMimeMappingMethodInfo = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);
if (getMimeMappingMethodInfo == null)
throw new SystemException("Couldnt find GetMimeMapping method");
if (getMimeMappingMethodInfo.ReturnType != typeof(string))
throw new SystemException("GetMimeMapping method has invalid return type");
if (getMimeMappingMethodInfo.GetParameters().Length != 1 && getMimeMappingMethodInfo.GetParameters()[0].ParameterType != typeof(string))
throw new SystemException("GetMimeMapping method has invalid parameters");
}
public static string GetMimeType(string filename)
{
lock (locker)
return (string)getMimeMappingMethodInfo.Invoke(mimeMapping, new object[] { filename });
}
}
public static class MimeExtensionHelper
{
static object locker = new object();
static object mimeMapping;
static MethodInfo getMimeMappingMethodInfo;
static MimeExtensionHelper()
{
Type mimeMappingType = Assembly.GetAssembly(typeof(HttpRuntime)).GetType("System.Web.MimeMapping");
if (mimeMappingType == null)
throw new SystemException("Couldnt find MimeMapping type");
getMimeMappingMethodInfo = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (getMimeMappingMethodInfo == null)
throw new SystemException("Couldnt find GetMimeMapping method");
if (getMimeMappingMethodInfo.ReturnType != typeof(string))
throw new SystemException("GetMimeMapping method has invalid return type");
if (getMimeMappingMethodInfo.GetParameters().Length != 1 && getMimeMappingMethodInfo.GetParameters()[0].ParameterType != typeof(string))
throw new SystemException("GetMimeMapping method has invalid parameters");
}
public static string GetMimeType(string filename)
{
lock (locker)
return (string)getMimeMappingMethodInfo.Invoke(mimeMapping, new object[] { filename });
}
}
.NET 4.5+
Обертка не требуется, вызовите открытый метод System.Web.MimeMapping.GetMimeMapping
напрямую.
Я объединил все эти подходы в моей служебной библиотеке, за исключением, может быть, №3. Кстати, номер 2 (urlmon.dll) не требует статического файла, он просто занимает несколько байтов независимо от того, откуда они пришли. Вот мой текущий класс
namespace Components
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Win32;
public sealed class MimeExtensionHelper
{
private MimeExtensionHelper() { }
/// <summary>Finds extension associated with specified mime type</summary>
/// <param name="mimeType">mime type you search extension for, e.g.: "application/octet-stream"</param>
/// <returns>most used extension, associated with provided type, e.g.: ".bin"</returns>
public static string FindExtension(string mimeType)
{
return ExtensionTypes.GetExtension(mimeType);
}
/// <summary>Finds mime type using provided extension and/or file's binary content.</summary>
/// <param name="file">Full file path</param>
/// <param name="verifyFromContent">Should the file's content be examined to verify founded value.</param>
/// <returns>mime type of file, e.g.: "application/octet-stream"</returns>
public static string FindMime(string file,bool verifyFromContent)
{
string extension = Path.GetExtension(file);
string mimeType = string.Empty;
try
{
if (!String.IsNullOrEmpty(extension))
mimeType = ExtensionTypes.GetMimeType(extension);
if (verifyFromContent
|| (String.IsNullOrEmpty(mimeType) && File.Exists(file)))
mimeType = FindMimeByContent(file,mimeType);
}
catch { }
return (mimeType ?? string.Empty).Trim();//"application/octet-stream"
}
/// <summary>Finds mime type for file using it's binary data.</summary>
/// <param name="file">Full path to file.</param>
/// <param name="proposedType">Optional. Expected file's type.</param>
/// <returns>mime type, e.g.: "application/octet-stream"</returns>
public static string FindMimeByContent(string file
,string proposedType)
{
FileInfo fi = new FileInfo(file);
if (!fi.Exists)
throw new FileNotFoundException(file);
byte[] buf = new byte[Math.Min(4096L,fi.Length)];
using (FileStream fs = File.OpenRead(file))
fs.Read(buf,0,buf.Length);
return FindMimeByData(buf,proposedType);
}
/// <summary>Finds mime type for binary data.</summary>
/// <param name="dataBytes">Binary data to examine.</param>
/// <param name="mimeProposed">Optional. Expected mime type.</param>
/// <returns>mime type, e.g.: "application/octet-stream"</returns>
public static string FindMimeByData(byte[] dataBytes,string mimeProposed)
{
if (dataBytes == null || dataBytes.Length == 0)
throw new ArgumentNullException("dataBytes");
string mimeRet = String.Empty;
IntPtr outPtr = IntPtr.Zero;
if (!String.IsNullOrEmpty(mimeProposed))
mimeRet = mimeProposed;
int result = FindMimeFromData(IntPtr.Zero
,null
,dataBytes
,dataBytes.Length
,String.IsNullOrEmpty(mimeProposed) ? null : mimeProposed
,0
,out outPtr
,0);
if (result != 0)
throw Marshal.GetExceptionForHR(result);
if (outPtr != null && outPtr != IntPtr.Zero)
{
mimeRet = Marshal.PtrToStringUni(outPtr);
Marshal.FreeCoTaskMem(outPtr);
}
return mimeRet;
}
[DllImport("urlmon.dll"
,CharSet = CharSet.Unicode
,ExactSpelling = true
,SetLastError = true)]
static extern Int32 FindMimeFromData(IntPtr pBC
,[MarshalAs(UnmanagedType.LPWStr)] String pwzUrl
,[MarshalAs(UnmanagedType.LPArray,ArraySubType = UnmanagedType.I1,SizeParamIndex = 3)] Byte[] pBuffer
,Int32 cbSize
,[MarshalAs(UnmanagedType.LPWStr)] String pwzMimeProposed
,Int32 dwMimeFlags
,out IntPtr ppwzMimeOut
,Int32 dwReserved);
private static MimeTypeCollection _extensionTypes = null;
private static MimeTypeCollection ExtensionTypes
{
get
{
if (_extensionTypes == null)
_extensionTypes = new MimeTypeCollection();
return _extensionTypes;
}
}
[Serializable]
[XmlRoot(ElementName = "mimeTypes")]
private class MimeTypeCollection : List<MimeTypeCollection.mimeTypeInfo>
{
private SortedList<string,string> _extensions;
private SortedList<string,List<string>> _mimes;
private void Init()
{
if (_extensions == null || _mimes == null
|| _extensions.Count == 0 || _mimes.Count == 0)
{
_extensions = new SortedList<string,string>(StringComparer.OrdinalIgnoreCase);
_mimes = new SortedList<string,List<string>>(StringComparer.OrdinalIgnoreCase);
foreach (var mime in this)
{
_mimes.Add(mime.MimeType,new List<string>(mime.Extensions));
foreach (string ext in mime.Extensions)
if (!_extensions.ContainsKey(ext))
_extensions.Add(ext,mime.MimeType);
}
}
}
public String GetExtension(string type)
{
Init();
return _mimes.ContainsKey(type) ? _mimes[type][0] : string.Empty;
}
public String GetMimeType(string extension)
{
Init();
return _extensions.ContainsKey(extension) ? _extensions[extension] : string.Empty;
}
public MimeTypeCollection()
{
this.Add(new mimeTypeInfo("application/applixware",new List<string>(new[] { ".aw" })));
this.Add(new mimeTypeInfo("application/atom+xml",new List<string>(new[] { ".atom" })));
// ... Whole list from apache's site
this.Add(new mimeTypeInfo("x-x509-ca-cert",new List<string>(new[] { ".cer" })));
try
{
using (RegistryKey classesRoot = Registry.ClassesRoot)
using (RegistryKey typeKey = classesRoot.OpenSubKey(@"MIME\Database\Content Type"))
{
string[] subKeyNames = typeKey.GetSubKeyNames();
string extension = string.Empty;
foreach (string keyname in subKeyNames)
{
string trimmed = (keyname ?? string.Empty).Trim();
if (string.IsNullOrEmpty(trimmed))
continue;
if (!String.IsNullOrEmpty(GetExtension(trimmed)))
continue;
string subKey = "MIME\\Database\\Content Type\\" + trimmed;
using (RegistryKey curKey = classesRoot.OpenSubKey(subKey))
{
extension = (curKey.GetValue("Extension") as string ?? string.Empty).Trim();
if (extension.Length > 0)
this.Add(new mimeTypeInfo(trimmed
,new List<string>(new[] { extension })));
}
}
}
}
catch (Exception ex)
{
string s = ex.ToString();
}
}
[Serializable]
public class mimeTypeInfo
{
[XmlAttribute(AttributeName = "mimeType")]
public String MimeType { get; set; }
[XmlElement("extension")]
public List<String> Extensions { get; set; }
public mimeTypeInfo(string mimeType,List<string> extensions)
{
MimeType = mimeType;
Extensions = extensions;
}
public mimeTypeInfo() { }
}
}
}
}
Nisus - вы бы хотели разместить где-нибудь весь исходный код вашей утилиты? это действительно было бы полезно. Благодарность!
Неважно ....
Я отредактировал файл определения apache, чтобы он содержал только записи с определенными расширениями, затем расширил код для загрузки типов / расширений из текстового файла во время выполнения. Возможно, это не изящно, но наверняка превосходит создание / поддержку 630 строк исходного кода для типов mime.
[в конструкторе для MimeTypeCollection вместо этого материала: this.Add (new mimeTypeInfo ("application / applixware", new List (new [ ] {".aw"})));]
// import mime/extension definition list to facilitate maintenance
string dir = AppDomain.CurrentDomain.BaseDirectory;
using (TextReader streamReader = new StreamReader(Path.Combine(dir, "MimeDefinitions.txt")))
{
string input;
while ((input = streamReader.ReadLine()) != null)
{
if (input.Substring(0, 1) != "#")
{
// text line format ::= [contenttype]<tab>[space delimited list of extensions, without dot]
string contentType = input.Group("0\t1");
string extensionList = input.Group("1\t1");
string[] extensions = extensionList.Split(" ".ToCharArray());
List<string> extensionSet = new List<string>();
foreach (string term in extensions)
{
extensionSet.Add("."+term);
}
this.Add(new mimeTypeInfo(contentType, extensionSet));
}
}
}
Я также обнаружил, что будет вызван метод Init (), а члены _extensions и _mime не будут полностью инициализированы, поэтому я изменил его на:
if (_extensions == null || _mimes == null || _mimes.Count != this.Count)
В любом случае, Теперь я расскажу о классе, который может обрабатывать необходимые мне внешние defs и локальный реестр.
Спасибо!